Teknisk artikel

Soft masks og transparensudfladning i Delphi

PDF Library for Delphi opretter begge slags PDF soft mask fra Delphi. SetImageSoftMaskEx knytter et maskebillede til et målbillede og kan skrive den /Matte-post, som forhåndsmultipliceret grafik har brug for. NewSoftMaskGraphicsState bygger en alpha- eller luminositetsmaske ud fra indfanget indhold og returnerer en graphics state, du anvender på efterfølgende tegning. Og når en forbruger slet ikke kan håndtere transparens, gengiver FlattenTransparency det visuelle resultat og erstatter hver side med det

Soft masks er, hvad PDF bruger til at udtrykke en gradient-udtoning, en vignet, et foto blendet ind i en baggrund, og enhver anden effekt, hvor opacitet varierer på tværs af en region. Konstant transparens er ét enkelt tal i graphics staten; en soft mask er en hel funktion af position, og indtil du kan oprette én, kan en hel designkategori ikke gengives

De to masketyper, og hvad hver af dem læser

En alpha-maske henter sine værdier fra alfakanalen af det maskerende indhold. En luminositetsmaske henter dem fra lysstyrken af det maskerende indhold, så et hvidt område er fuldt uigennemsigtigt, og et sort område fuldt gennemsigtigt. Luminositet er den, designere griber til, fordi at male en gråtonegradient er en naturlig måde at beskrive en udtoning på

Form-soft masks bygges ud fra indfanget indhold, og flere detaljer er faste frem for valgfrie. Det indfangede indhold bliver en isoleret transparensgruppe i DeviceRGB, så masken evalueres i et kendt farverum. Baggrundsfarven skal derfor have tre komponenter, der matcher den gruppe. Overførselsfunktionen accepterer /Identity eller et gyldigt funktionsobjekt, hvilket lader dig omforme maskekurven uden at genmale grafikken

Diagram, der sammenligner luminositets- og alpha-soft masks, der fodrer NewSoftMaskGraphicsState, med en påmindelse om, at graphics staten fortsætter, indtil den ryddes
Luminositetsmasker læser lysstyrke, mens alpha-masker læser dækning, og NewSoftMaskGraphicsState pakker begge ind i en vedvarende graphics state
uses
  PDFlibrary;

var
  Lib: TPDFlib;
  MaskCapture, MaskGS, PhotoID: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.LoadFromFile('brochure.pdf', '');

    // Side 4 rummer en gråtonegradient malet til brug som maske
    MaskCapture := Lib.CapturePage(4);

    MaskGS := Lib.NewSoftMaskGraphicsState(MaskCapture,
      PDF_SOFT_MASK_LUMINOSITY, '0 0 0', '/Identity');

    Lib.SelectPage(1);
    Lib.SetGraphicsState(MaskGS);
    PhotoID := Lib.AddImageFromFile('hero.jpg', 0);
    Lib.SelectImage(PhotoID);
    Lib.DrawImage(40, 700, 515, 260);        // toner ud under masken

    // ExtGState-indstillinger fortsætter: afslut scope'et eksplicit
    Lib.SetGraphicsState(Lib.NewSoftMaskGraphicsState(0,
      PDF_SOFT_MASK_NONE, '', ''));

    Lib.SaveToFile('brochure-masked.pdf');
  finally
    Lib.Free;
  end;
end;

Det sidste trin er ikke dekoration. Graphics state-parametre fortsætter, indtil de ændres, og at anvende en almindelig graphics state bagefter rydder ikke en aktiv soft mask. Uden et eksplicit /SMask /None arver alt, der tegnes efter den maskerede grafik, masken, hvilket er én af de mere forvirrende fejl at diagnosticere visuelt

Billedmasker og Matte-posten

Til maskering på billedniveau normaliseres maskebilledet først til DeviceGray, så en maske leveret i et vilkårligt farverum opfører sig forudsigeligt. Den valgfrie /Matte-post, én til fire komponenter afhængigt af billedets farverum, fortæller en forbruger, at billeddataene er forhåndsmultipliceret mod den farve, hvilket forhindrer den mørke halo, der opstår, når forhåndsmultipliceret grafik sammensættes, som var det ren alfa

Diagram, der viser, hvordan en manglende Matte-post giver mørke haloer, mens en deklareret Matte sammensætter rent, ved siden af PDF 1.4- og PDF/A- og PDF/X-sikkerhedsforanstaltninger
En deklareret /Matte forhindrer den mørke halo fra forhåndsmultipliceret grafik, mens PDF/A-1- og PDF/X-1-filer afvises, før noget objekt ændres

To sikkerhedsforanstaltninger betyder noget her. PDF/A-1 og PDF/X-1 forbyder transparens, og kaldet afviser, før noget objekt ændres, frem for at producere en fil, der senere fejler validering. Og en vellykket soft mask kræver PDF 1.4, som biblioteket sætter automatisk — transparens eksisterede ikke før den version, og en 1.3-header på en fil, der indeholder soft masks, er ganske enkelt falsk

Gentagne states genbruges: den samme indfangede formular, maske-type, baggrund og overførselsfunktion-signatur giver det samme graphics state-objekt frem for et nyt pr. kald. På et dokument, der maskerer hundrede billeder identisk, er det nioghalvfems objekter, der aldrig skrives

Hvorfor udflade, og hvad udfladning egentlig gør

Transparens er stadig den mest almindelige kilde til "det ser rigtigt ud på skærmen og forkert på trykket". Ældre RIP'er, nogle myndighedsindsendelsessystemer og PDF/X-1a kræver alle en fil helt uden levende transparens

Udfladning her er bevidst bogstavelig: hver side i det ønskede interval gengives ved en valgt DPI mod en uigennemsigtig baggrund, og sideindholdet og ressourcerne erstattes af det ene billede. Fordi rendereren producerer det endelige sammensatte resultat, dækker dette alt på én gang — transparensgrupper, blend-tilstande, soft masks, mønstre og indlejrede formularer — uden per-konstruktion approksimationslogik, der kan gå galt. Spids-rastermodhukommelsen forbliver begrænset til én side

Pipeline-diagram af FlattenTransparency, der gengiver hver ønsket side ved 300 DPI mod en uigennemsigtig baggrund og gemmer en flad, trykklar PDF 1.3-fil
Hver ønsket side gengives én gang ved den valgte DPI og returneres som ét uigennemsigtigt billede, gemt i en sanddru PDF 1.3-fil
// Udflad side 1-8 ved 300 DPI på hvid, og gem så som PDF 1.3
Lib.FlattenTransparency('1-8', 300, $FFFFFF, 0);
Lib.SaveToFile('press-ready.pdf');

Prisen er lige så bogstavelig: outputtet er et billede, så tekst kan ikke længere markeres eller søges i, og vektorkanter resamples ved den valgte DPI. Udfladning er et leveringstrin, ikke et redigeringstrin. Behold det transparente original, og udflad en kopi

Roterede sider, user units og sideboksene

En roteret side kræver omhu, en naiv implementering springer over. Efter gengivelse skrives den visuelle bredde og højde tilbage til MediaBox'en, user unit'en foldes ind i den effektive DPI og den nye sidestørrelse, og /Rotate-posten, user unit'en og de hjælpende sideboksene fjernes

At springe det over giver en fil, hvor det udfladede billede er korrekt, men en fremviser roterer det igen, eller skalerer det med en user unit, der ikke længere gælder. At fjerne boksene frem for at genberegne dem er det rigtige valg, fordi en TrimBox, der beskriver geometrien før udfladning, er værre end slet ingen TrimBox

Annotationer og formularfelter gengives som standard ind i det statiske billede, og de interaktive objekter fjernes, hvilket er, hvad en trykklar leverance ønsker. Beholder du de interaktive objekter i stedet, slås rendererens annotationspassering fra, så intet tegnes to gange

Versionstjekket, der scanner alt

At gemme som PDF 1.3 kræver, at ingen transparens er tilbage nogen steder, og tjekket før gemning undersøger hvert indirekte objekt, ikke kun dem, der kan nås fra sider. Det er strengere, end det først lader til, og det er korrekt: en forældreløs soft mask, efterladt af en tidligere redigering, er stadig i filen, og en forbruger, der gennemløber objekter frem for sider, vil finde den

For at gøre nedgraderingen opnåelig kører en mark-and-sweep-passering som standard, når hver målside er blevet erstattet med succes, og frigør de uopnåelige objekter. Konsekvensen at planlægge for er, at billed-, indfanget-side- og graphics state-identifikatorer, opnået før den sweep, muligvis ikke længere er gyldige bagefter. Genindhent de ressourceidentifikatorer, du har brug for, før du fortsætter med at redigere, eller deaktivér sweep'en og acceptér, at versionen så ikke kan sænkes

To følgesvende fuldender billedet. Vektorgrafik, der bruger shadings og gradienter frem for masker, er dækket i vektorgrafik, shaders og gradienter, og det er ofte den bedre rute, når effekten kan udtrykkes som en shading. Og hvis grunden til, at du udflader, er et farvekrav frem for et transparenskrav, bevarer konverteringsstien i omfarvning af et dokument til et andet farverum levende tekst, hvor udfladning ikke ville

Oprettelse af soft masks, udfladning og gengivelsesmotoren bag dem leveres i ét bibliotek til Delphi, C++Builder og Free Pascal; den komplette funktionsliste findes på PDF Library for Delphi-siden