Article technique

Épreuvage Surimpression CMYK et Périphériques Rendu HotPDF

Une boîte cyan siège sur un fond jaune, et l'état graphique qui la peint porte /op true et /OPM 1. À l'écran, le chevauchement est un cyan plat. Sur la feuille de presse, le même chevauchement sort vert, parce que le RIP a laissé la plaque jaune tranquille et a posé le cyan par-dessus. Les deux résultats suivent le fichier à la lettre ; le rendu écran n'a simplement jamais demandé ce qu'un périphérique d'imagerie fait de ce drapeau, si bien qu'une approbation donnée à l'écran couvre une couleur qui n'atteint jamais le papier

Pourquoi une page s'imprime-t-elle différemment de son aperçu ?

La surimpression est une instruction au périphérique de sortie au sujet des plaques, et un écran RGB n'a pas de plaques. ISO 32000-1 §8.6.7 définit ce qui arrive quand l'entrée OP (trait) ou op (remplissage) d'un ExtGState est vraie : les colorants que la peinture courante ne nomme pas gardent ce qui était déjà sur leur plaque, au lieu d'être effacés à zéro. Un objet cyan peint ainsi ne retire rien à la plaque jaune. Un lecteur qui compose en RGB n'a nulle part où garder le jaune, donc il peint le cyan par-dessus et passe à autre chose

Aucune des deux sorties n'est cassée. Le désaccord est bâti dans les deux modèles d'imagerie, et il reste invisible jusqu'à ce que quelqu'un tienne une épreuve imprimée à côté du moniteur. C'est tard dans le travail pour un designer qui a mis du texte noir en Knockout par erreur, ou qui a laissé un logo blanc en surimpression en espérant qu'il paraisse

Comparaison de surimpression CMYK dans HotPDF où un lecteur ordinaire détourne le jaune sous le cyan tandis que l'aperçu de surimpression épreuve les deux encres de quadri et révèle du texte blanc surimprimé par accident
Un visualiseur simple peint la seule encre supérieure tandis que l'épreuve overprint cumule les deux encres, exposant des pièges comme du texte blanc surimprimé par accident

Activer l'épreuve avec RenderOverprintPreview

HotPDF expose l'épreuve comme un booléen du document, THotPDF.RenderOverprintPreview, qui vaut False par défaut. Avec lui posé, le rendu bitmap suit les plaques de procédé sous chaque peinture en surimpression et applique les règles du §8.6.7 avant d'écrire le pixel, donc les chevauchements montrent la combinaison d'encres que la presse produirait. Laisser le défaut éteint est juste pour la consultation ordinaire, car les lecteurs d'un PDF de bureau attendent qu'il ressemble à ce que leur lecteur habituel montre. Activez-le dans l'étape dont la sortie va à un opérateur prépresse

var
  Pdf: THotPDF;
  Device: THPDFBitmapRenderDevice;
  Proof: TBitmap;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.LoadFromFile('cover-cmyk.pdf');
    Pdf.RenderOverprintPreview := True;    // éprouver les plaques, le défaut est False
    Device := THPDFBitmapRenderDevice.Create;
    try
      if Pdf.RenderLoadedPageToDevice(0, 150, Device) then
      begin
        Proof := Device.TakeBitmap;        // l'appelant possède Proof à partir d'ici
        try
          Image1.Picture.Assign(Proof);
        finally
          Proof.Free;
        end;
      end;
    finally
      Device.Free;
    end;
  finally
    Pdf.Free;
  end;
end;

Les règles de plaques dépendent de l'espace de couleur de la peinture en surimpression, et elles méritent d'être connues parce que chacune explique une surprise différente sur une épreuve :

  • DeviceCMYK sous /OPM 1 : un composant à zéro laisse sa plaque intacte, un composant non nul la remplace. Cyan 100 / jaune 0 sur un fond jaune garde le jaune et devient vert
  • DeviceGray : la peinture ne nomme que la plaque noire, donc le cyan, le magenta et le jaune en dessous survivent. Un logo blanc DeviceGray mis en surimpression sur un fond CMY disparaît donc
  • Separation et DeviceN : un colorant nommé Cyan, Magenta, Yellow ou Black remplace directement cette plaque de procédé, /None ne peint rien du tout, et /All écrit chaque plaque de procédé
  • Colorants spot : tout autre nom est traité comme une encre spot ; sa transformée de teinte donne une couleur alternative, qui est multipliée sur les plaques de procédé en dessous, si bien que la spot assombrit ce qu'elle couvre au lieu de le remplacer

L'épreuve s'applique aux chemins remplis et tracés et au texte, y compris le texte en mode de rendu trait, où le drapeau de trait OP décide à la place de op. Images, images en ligne et ombrages sh continuent par leurs pipelines de couleur raster complets et peignent avec leur opacité ordinaire. En pratique cela couvre ce que les rapports de prévol signalent le plus : règles de surimpression, lignes de coupe, texte et aplats

La transparence reste vivante pendant que l'épreuve est active. Un groupe de transparence avec knockout posé fait toujours son knockout, et le groupe est composé dans la même passe que les règles de surimpression, donc un fichier prêt pour impression avec une illustration transparente sur un fond noir en surimpression éprouve les deux effets ensemble. En avoir un juste et l'autre faux produirait juste une autre épreuve fausse

Le réglage participe aussi à l'identité des rendus en cache. RenderLoadedPageToBitmapCached cale ses entrées sur page, DPI et une variante bâtie depuis les réglages de rendu qui inclut RenderOverprintPreview, et le niveau disque emploie la même variante. Un lecteur qui bascule entre aperçu normal et épreuve obtient deux entrées de cache séparées et n'a jamais besoin d'un appel à InvalidateRenderedPageCache juste parce que le commutateur a changé

Le piège /OPM 0 dans les fichiers DeviceCMYK

Voici le cas qui envoie les gens chercher un bogue. Un fichier pose /op true sur un remplissage cyan DeviceCMYK mais laisse OPM à son défaut de 0, puis l'épreuve montre quand même le cyan faisant knockout du jaune. L'épreuve a raison. Sous le mode de surimpression 0, le §8.6.7 dit qu'une peinture DeviceCMYK pose les quatre colorants de procédé, zéros compris, donc le composant jaune zéro remplace la plaque jaune exactement comme le ferait un knockout. Le mode de surimpression 0 ne protège que les plaques que la peinture ne nomme pas, ce qui pour une couleur CMYK à quatre composants signifie les plaques spot et rien d'autre

Sur les plaques de procédé qu'une épreuve composite montre, le mode 0 et un knockout simple donnent les mêmes pixels, donc HotPDF peint ces objets DeviceCMYK comme des knockouts ordinaires. Pour qu'un objet CMYK surimprime les autres encres de procédé, l'ExtGState qui porte /op true a aussi besoin de /OPM 1. Quand une épreuve et l'intention du designer sont en désaccord sur un objet DeviceCMYK, ouvrez cet ExtGState et cherchez l'entrée OPM avant de suspecter quoi que ce soit d'autre

La surprise inverse existe aussi. Sous /OPM 1, le blanc CMYK est quatre zéros, et quatre zéros en surimpression laissent chaque plaque en l'état. Du texte blanc mis en surimpression disparaît sur la feuille, et l'épreuve montre sa disparition, ce qui est toute la raison d'en faire une

Trois périphériques derrière RenderLoadedPageToDevice

THotPDF.RenderLoadedPageToDevice(PageIndex, DPI, Device) est un point d'entrée unique dont la cible est décidée par l'objet périphérique que vous passez. Il lève une exception pour un périphérique nil, traite un DPI sous 1 comme 150, et renvoie ce que le périphérique rapporte depuis sa méthode Execute. THPDFRenderDevice est la base abstraite avec deux membres virtuels : Kind, qui renvoie rdkBitmap, rdkDeviceContext ou rdkEnhancedMetafile, et Execute(Document, PageIndex, DPI)

Les trois périphériques livrés possèdent leur sortie de manières différentes :

  • THPDFBitmapRenderDevice tient un TBitmap dans sa propriété Bitmap et le libère dans son destructeur sauf si TakeBitmap vous l'a remis d'abord
  • THPDFDeviceContextRenderDevice.Create(ADC, AWidth, AHeight) dessine dans un HDC que vous avez déjà et ne possède rien ; le constructeur lève sur un DC zéro ou une taille non positive, et aucun fond n'est peint, donc un DC écran a besoin de son propre remplissage blanc
  • THPDFMetafileRenderDevice tient un TMetafile jusqu'à ce que TakeMetafile le transfère. Texte et chemins vectoriels restent évolutifs dans le métafichier amélioré, tandis que les XObjects image arrivent rastérisés
Architecture de rendu HotPDF éventailant un appel RenderLoadedPageToDevice vers les périphériques de rendu bitmap, contexte de périphérique d'impression et métafichier amélioré avec leurs valeurs Kind et leurs règles de possession
Un seul appel de rendu se déploie vers des périphériques bitmap, device context et métafichier dont Kind signale la cible et dont les méthodes Take transfèrent la possession

La possession suit les règles Delphi ordinaires. Lisez la propriété Bitmap ou Metafile quand l'objet a seulement besoin de vivre aussi longtemps que le périphérique ; appelez la méthode Take quand il doit lui survivre. Prenez le bitmap, libérez le périphérique, oubliez le bitmap, et la fuite grandit avec le compte de pages : invisible sur un échantillon de cinq pages, évidente sur un lot de cinq cents. Donnez à chaque objet son propre try/finally et la question de qui libère quoi se répond seule

Dispatchez sur Kind dans le code d'application au lieu de tester is THPDFBitmapRenderDevice. Comme Execute et Kind sont des méthodes virtuelles publiques, vous pouvez écrire votre propre classe de périphérique, et le code qui vérifie le genre continue de marcher quand une des vôtres tient lieu de périphérique livré

Pourquoi un rendu imprimante atterrit-il dans un coin ?

La voie contexte de périphérique dimensionne la page depuis l'argument DPI, pas depuis la largeur et la hauteur que vous passez. Le moteur de rendu met à l'échelle les unités PDF par DPI / 72 et n'emploie la hauteur que pour ancrer l'origine de la page au bas de la surface. Codez 300 en dur et envoyez le travail à une imprimante 600 dpi, et la page sort à moitié taille, poussée au coin inférieur gauche de la feuille. La résolution imprimante est une propriété du pilote, donc demandez-la au pilote :

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
    // demandez au pilote ; 300, 600 et 1200 dpi sont tous courants
    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;            // échange pour les pages 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;

La largeur et la hauteur viennent de la boîte visible de la page, la CropBox rognée à la MediaBox, à la résolution propre de l'imprimante, et l'appelant les échange pour les pages pivotées avant de créer le périphérique. Cela correspond à ce que le moteur de rendu attend quand il ancre l'origine

L'épreuve de surimpression ne descend pas par ce chemin. Les périphériques contexte de périphérique et métafichier émettent des appels GDI droit dans la cible, et les règles de plaques ont besoin des pixels déjà en dessous de chaque peinture, ce que seul le rendu bitmap possède. Pour une épreuve papier, rendez le bitmap d'épreuve et étirez-le sur le canvas imprimante. Un petit périphérique maison garde cela derrière le même point d'entrée :

type
  // un périphérique à vous : bitmap d'épreuve, puis étiré sur l'imprimante
  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;  // laisser le réglage de l'appelant comme il était
  end;
  Result := Proof <> nil;
  if Result then
  try
    Printer.Canvas.StretchDraw(
      Rect(0, 0, Printer.PageWidth, Printer.PageHeight), Proof);
  finally
    Proof.Free;
  end;
end;

Appelez-le entre Printer.BeginDoc et Printer.EndDoc avec un DPI qui donne au bitmap assez de pixels pour la feuille, autour de 200 à 300 pour une épreuve format lettre. Le rectangle d'étirement ci-dessus remplit la zone imprimable ; gardez le rapport d'aspect de la page dedans si la page et le papier diffèrent de forme

Où l'épreuvage se place à côté du prévol

L'épreuve répond à une question : quelles encres survivent où les objets se chevauchent. Elle est composée sur le même bitmap RGB 24 bits que tout autre rendu, donc ses couleurs montrent la combinaison d'encres plutôt qu'une couleur de feuille mesurée. Les conditions de presse sont une question de gestion de couleur, et le document les traite via ConfigureRenderICCWorkflow, qui prend un profil d'épreuve, un profil de sortie et un drapeau de compensation du point noir, et ClearRenderICCWorkflow pour les lâcher

L'endroit le plus productif pour un rendu d'épreuve est à côté des contrôles que vous exécutez déjà. Une passe de prévol rapporte que du texte noir est en surimpression ; le rendu d'épreuve montre à l'opérateur ce que cela fait sur la page ; les deux atterrissent dans le même rapport. Le travail d'emballage tend à mélanger surimpression et encres spot, et la visite guidée de la séparation et du rendu des couleurs spot DeviceN couvre le versant colorant de la même page, y compris les vues à plaque unique via RenderLoadedPageSeparationPlate. Les articles sur le rendu d'une page PDF en bitmap et l'impression d'un PDF chargé via TPrinter couvrent les deux cibles de périphériques sous leur forme simple

Tout cela tourne en code Delphi et C++Builder natif sans DLL de rendu à livrer à côté de l'exécutable. La page du composant HotPDF Delphi liste les fonctionnalités de rendu et de prépresse et propose un build d'essai pour faire tourner ces exemples contre vos propres fichiers d'impression