Egy tranzakciós nyomda egyetlen soros indoklással küldi vissza az Ön 80 000 oldalas kivonat-sorozatát: „nem PDF/VT, a RIP nem tudja gyorsítótárazni”. A fájl jól nyílik meg az asztalán lévő összes nézőkében, a színek megfelelőek, az adatok helyesen lettek összevonva. A digitális nyomdagépnek azonban nem erre volt szüksége. A nagy sebességű, változó adatú nyomtatás (variable-data printing) azon áll vagy bukik, hogy a nyomdagép fel tudja-e ismerni, hogy az 1. oldalon lévő ügyféllogó blokk bájt-pontosan megegyezik a 40 000. oldalon lévővel, így azt csak egyszer rendereli le, és újrahasznosítja. A PDF/VT az a szabvány, amely ezt az ígéretet géppel ellenőrizhetővé teszi, és a „helyesnek tűnik” állapot éppen a csapda, mert a RIP által olvasott szerkezet láthatatlan a képernyőn
Mit szabványosít a PDF/VT, és miért a PDF/X az első
A PDF/VT (ISO 16612-2:2010) nem egy új fájlformátum. Ez egy optimalizációs metaadat-réteg, amelyet egy PDF/X fájlhoz rögzítenek, és ez a sorrend meghatározó. A szabvány három megfelelőségi szintet határoz meg, de ezek közül csak kettő jelöl PDF-fájlt: a PDF/VT-1, amely egyetlen önálló dokumentum, és a PDF/VT-2, amely egy fájlkészlet-modell (file-set model), ahol az oldalak közös külső erőforrásokra hivatkoznak. A harmadik token, amellyel találkozhat, a PDF/VT-2s, egyáltalán nem fájlszintű érték; ez az 'A' mellékletben leírt MIME folyamfejlécben (MIME stream header) él. Ha olyan kódot talál, amely a GTS_PDFVTVersion = "PDF/VT-2s" értéket bélyegzi a dokumentum XMP metaadatába, az a kód hibás
Az egyetlen fájlra vonatkozó vitathatatlan szabály a PDF/X alap. Az ISO 16612-2 §6.2.1 előírja, hogy minden PDF/VT-1 fájlnak érvényes PDF/X-4 fájlnak is kell lennie. A PDF/VT-2 fájlkészletének a §6.2.2 szerint ehelyett a PDF/X-4p, PDF/X-5g vagy PDF/X-5pg szabványra kell épülnie. Ez az oka annak, hogy a PDF/VT író nem tud csak néhány azonosító kulcsot hozzáfűzni: magával kell vinnie a teljes PDF/X-4 jelölőkészletet, ami egy OutputIntent-et, egy beágyazott ICC célprofilt, a hozzáillő XMP és dokumentum-Info bejegyzéseket, egy trailer /ID-t és a titkosítás hiányát jelenti. Ha ezek közül bármelyiket kihagyja, olyan fájlt kap, amely PDF/VT-nek vallja magát, de elbukik abban a pillanatban, amikor egy megfelelő szoftver ellenőrzi az alapot. A PDFiumPas a PDF/X-4 réteget a PDF/VT mentés részeként kezeli, így nem kell először egy külön SaveAsPdfX-et hívnia; az injektor mindkét réteget egyetlen menetben írja le
Fájl kiírása a SaveAsPdfVT segítségével
A minimális híváshoz nincs szükség másra, mint egy aktív dokumentumra, mivel a TPdfVTSaveOptions.Default egy beépített sRGB ICC profilt és a pvc1 megfelelőséget biztosítja. A mentés belsőleg három lépést hajt végre: eltávolít minden védelmet (mivel a sima szöveges jelölők injektálása egy titkosított objektumfolyamba megrongálná azt), áthidalja a dokumentum meglévő Info szótárát és a trailer /ID-t a jelölőkészletbe, hogy az XMP és az Info értékek megegyezzenek, majd inkrementális frissítéssel hozzáfűzi a PDF/X-4 és PDF/VT objektumokat
var
Pdf: TPdf;
begin
Pdf := TPdf.Create(nil);
try
if Pdf.LoadFromFile('statements-merged.pdf') then
begin
// Default options: built-in sRGB OutputIntent, PDF/VT-1, synthesised DPart
if Pdf.SaveAsPdfVT('statements-pdfvt.pdf') then
Writeln('PDF/VT-1 written')
else
Writeln('Save failed (document not active?)');
end;
finally
Pdf.Free;
end;
end;
A valós produkciós kimenethez szinte mindig felül szeretné írni az OutputIntent-et a nyomdagépének megfelelő jellemzőkkel, a generic sRGB helyett. Adja meg az ICC bájtokat és a feltétel-azonosítókat a TPdfVTSaveOptions segítségével:
var
Pdf: TPdf;
Opt: TPdfVTSaveOptions;
Icc: TBytes;
begin
Pdf := TPdf.Create(nil);
try
Pdf.LoadFromFile('directmail-merged.pdf');
Icc := LoadIccProfile('GRACoL2013_CRPC6.icc'); // your own loader
Opt := TPdfVTSaveOptions.Default;
Opt.Conformance := pvc1; // a pvc2 a kiírás során pvc1-re normalizálódik
Opt.IccProfileData := Icc;
Opt.OutputConditionIdentifier := 'CGATS21_CRPC6';
Opt.OutputCondition := 'Commercial print, coated, CRPC6';
Opt.RegistryName := 'http://www.color.org';
Opt.Title := 'Spring 2026 Direct Mail Run';
Opt.Trapped := ptvFalse; // PDF/X Info /Trapped state
Pdf.SaveAsPdfVT('directmail-pdfvt.pdf', Opt);
finally
Pdf.Free;
end;
end;
Egy részlet ebben a kódrészletben szándékos védőkorlát, nem pedig olyan korlátozás, amellyel vitatkozni lehetne. Az Opt.Conformance := pvc2 beállítás nem hoz létre PDF/VT-2 fájlt. Az író minden nem pvc1 kérést vissza-normalizál pvc1-re, mivel a PDF/VT-2 egy fájlkészlet-formátum (file-set format), és egy olyan egyfájlos író, amely egy kimeneti dokumentumot fűz hozzá, fizikailag nem tudja összeállítani a §6.2.2 által megkövetelt külső erőforráskészletet. A pvc2 érték az olvasási útvonalhoz létezik, így a ValidatePdfVT fel tudja ismerni és jelenteni tudja a meglévő fájlkészlet-dokumentumot; ez nem írási célpont
A DPart-fa: a szerkezet, amelyet a RIP valójában olvas
A PDF/VT szíve a Document Part (DPart) hierarchia. Ez teszi lehetővé a nyomda számára, hogy egy hosszú sorozatot rekordokra tagoljon, a rekordokat címzettek vagy postai kötegek szerint csoportosítsa, és Document Part Metaadatokat csatoljon hozzájuk, így a feldolgozó berendezések irányítani és számlázni tudják az egyes darabokat. Az ISO 16612-2 §6.5 fekteti le a huzalozást: a katalógus egy /DPartRoot-ot hordoz, a gyökér DPart-csomópont egy /DPartRootNode-ot és egy /NodeNameList-et hordoz, amely megnevezi a hierarchia minden szintjét, a levél DPart-ok az oldafa tartományait fedik le, és minden olyan oldal, amely egy részhez tartozik, egy oldalszintű /DPart bejegyzésen keresztül mutat vissza a levelére
Ha a forrásdokumentum már tartalmaz használható hierarchiát, a SaveAsPdfVT megőrzi azt. Ha nem, az író szintetizál egy megengedő, minimálisat: egyetlen dokumentumszintű DPart-ot, amely sorrendben átível a jelenlegi oldafán, egy-egy /DPart visszahivatkozással a működő oldalszintű objektumokhoz csatolva, valamint egy egyszintű /NodeNameList [/Document] listát. Legyen őszinte magával kapcsolatban azzal kapcsolatban, hogy mi ez a minimális fa. Ez egy strukturális horgony, amely megfelel a §6.5 formai követelményeinek; ez nem üzleti metaadat. Nem képes címzetteket, postai küldeményhatárokat vagy terméktételeket feltalálni, mivel ez az információ soha nem szerepelt a forrás. Ha címzettenkénti adatai vannak, akkor a mélyebb DPart-fa felépítését magának kell elvégeznie, és ki kell terjesztenie a /NodeNameList-et a létrehozott szintekhez igazítva
Ellenőrzés, amely túlmutat a kulcs-jelenlét vizsgálatán
A ValidatePdfVT egy TPdfVTValidationResult rekorddal tér vissza, amely három dolgot tartalmaz: az észlelt Conformance szintet, a Issues készletet és egy IsCompliant segédfunkciót, amely csak akkor igaz, ha a megfelelőség valós szintű és a hibák halmaza üres. A hibák felsorolása szándékosan részletes, így a sikertelen eredmény megmondja, melyik záradékot mulasztotta el, ahelyett, hogy csak annyit mondana: „érvénytelen”:
var
Pdf: TPdf;
Res: TPdfVTValidationResult;
begin
Pdf := TPdf.Create(nil);
try
Pdf.LoadFromFile('statements-pdfvt.pdf');
Res := Pdf.ValidatePdfVT;
if Res.IsCompliant then
Writeln('PDF/VT compliant: ', VTLevelName(Res.Conformance))
else
begin
if pvviMissingDPartRoot in Res.Issues then
Writeln('DPart hierarchy missing or unusable');
if pvviMissingPdfXIdentifier in Res.Issues then
Writeln('PDF/X-4 base identifier absent');
if pvviMissingOutputIntent in Res.Issues then
Writeln('OutputIntent / ICC profile missing');
if pvviEncryptionPresent in Res.Issues then
Writeln('Encrypted - PDF/X forbids this');
end;
finally
Pdf.Free;
end;
end;
A két leginkább megértendő ellenőrzés a megfelelőségi párosítás és a DPart-bejárás, mivel mindkettő túl megengedő volt korábban, és a specifikációhoz igazítva szigorításra került. A párosítási oldalon az ellenőrző pontos egyezést vizsgál, nem pedig azt, hogy „bármilyen PDF/X megteszi”: egy PDF/VT-1 fájl csak PDF/X-4 alapon fogadható el, egy PDF/VT-2 fájl pedig csak PDF/X-4p, PDF/X-5g vagy PDF/X-5pg alapon. Egy PDF/X-1a alapra épülő PDF/VT-1 jelölőt a rendszer jelzi, nem pedig átengedi
A DPart-bejárás az, ahol a szigor nagy része lakozik. Nem elég, ha a katalógus rendelkezik /DPartRoot kulccsal, mert egy hamis üres objektum vagy egy oldal-linkek nélküli objektum továbbra sem használható. A HasValidDPartHierarchy és a rekurzív ValidateDPartNode felkutatja a teljes struktúrát: követik a szülő-linkeket, elutasítják a duplikált gyermekeket és ciklusokat, megkövetelik, hogy a /Start és a /DParts kölcsönösen kizárják egymást, és megkövetelik, hogy a levél oldaltartományai mélységi sorrendben fedjék le az oldafát, ahol az egyes oldalak /DPart bejegyzései az őket tartalmazó levélre mutatnak. Mindezek a belső hibák az egyetlen pvviMissingDPartRoot probléma-bitbe sűrűsödnek össze, ahelyett, hogy kibővítenék a nyilvános enumot, így ezt az egyetlen jelzőt úgy kezelje, mint „a DPart hierarchia használhatatlan”, nem pedig szó szerint úgy, hogy „a gyökérkulcs hiányzik”
Három szintaktikai csapda, amelyet az ellenőrző immár kényszerít
Az §6.5 4. táblázatával szembeni egymást követő vizsgálatok olyan formákat tártak fel, amelyeket a korábbi verziók elfogadtak, de a szabvány nem. Ezek olyan dolgok, amelyeket egy kézzel épített DPart-fa gyakran elront, ezért érdemes őket kifejezetten megemlíteni:
- A
/DPartstömbök tömbje, nem pedig lapos tömb. A külső tömb minden elemének közvetett hivatkozású tömbnek kell lennie. Egy lapos/DParts [9 0 R]elutasításra kerül; a megfelelő forma a/DParts [[9 0 R] [10 0 R]]. Ez megakadályozza, hogy a nem-hierarchikus szerkezet érvényes szintnek álcázza magát - Az
/Endcsak valódi többoldalas tartományt jelöl. Egy levél DPart csak akkor hordozhat/End-et, ha/Start-tal is rendelkezik, és a/End-nek később kell esnie az oldafa sorrendjében, mint a/Start-nak. Egy elfajult/Start 3 0 R /End 3 0 Rmostantól használhatatlanná teszi a hierarchiát ahelyett, hogy egyoldalas részként olvasná be - A
/NodeNameListneveknek túl kell élniük a PDF név-feloldást mint XML NMTOKEN-ek. Egy olyan név, mint a/Bad#20Nameszóközöket tartalmazóvá alakul vissza, ami nem érvényes token. Az implementáció elvégez egy könnyű ASCII-ellenőrzést (betűk, számjegyek,.,-,_,:, valamint a nem ASCII bájtok), amely kiszűri a szóközöket és határoló hibákat anélkül, hogy elutasítaná a legitim lokalizált vagy gyártó-specifikus neveket
XMP jelölők: ugyanazon tulajdonság kétféle kiírási módja
A PDF/VT azonosítás az XMP-ben a pdfvtid névtér alatt él, konkrétan a GTS_PDFVTVersion és GTS_PDFVTModDate tulajdonságokkal, a szabványos xmp:CreateDate és xmp:ModifyDate mellett. Egy finomság, amely téves „hiányzó” jelentéseket okoz a naiv olvasókban, az az, hogy ezek bármelyike kétféleképpen szerializálható: elem-szövegként (<pdfvtid:GTS_PDFVTVersion>PDF/VT-1</pdfvtid:GTS_PDFVTVersion>) vagy RDF-attribútumként a leíró elemen. A PDFiumPas mindkét formátumot beolvassa, így egy másik eszköz által attribútum-stílusban írt fájl nem kap büntetést. Kényszeríti továbbá a §6.3 konzisztencia-szabályát is, miszerint a GTS_PDFVTModDate-nek meg kell egyeznie a xmp:ModifyDate-tel; az eltérés a pvviModDateMismatch hibát vonja maga után
Még egy szabály ugyanabból a záradékból: az ismeretlen GTS_PDFVTVersion érték pvcUnknown marad, ahelyett, hogy vissza-normalizálódna pvcNone-ra. Ez a különbségtétel operatív szempontból fontos. A pvcNone azt jelenti, hogy „egyáltalán nincs PDF/VT jelölő, egy közönséges PDF”, míg a pvcUnknown azt, hogy „valami olyan verziót bélyegzett be, amelyet ez az ellenőrző nem ismer fel” (köztük a PDF/VT-2s esetet). A kettő összevonása elrejtene egy hibás fájlt egy közönséges dokumentummal azonos kosárban
Ahor a garancia véget ér
Érdemes pontosan tisztázni ezen metódusok ígéretének határait, mert a változó adatú nyomtatásnak (variable-data print) komoly anyagi tétje van. A DPart és a párosítási ellenőrzések bájtszintű strukturális ellenőrzést jelentenek. Megerősítik, hogy az optimalizációs váz, a PDF/X-4 alapjelölők, az OutputIntent és az XMP jelen vannak és belsőleg következetesek. Ugyanakkor ezek nem jelentenek tartalmi szintű PDF/X-4 preflight-ot: nem ellenőrzik, hogy minden szín a deklarált kimeneti feltételeken belül van-e, hogy minden betűtípus be van-e ágyazva, vagy hogy nem csúszott-e be tiltott transzparencia-keverési határeset. Egy bérnyomdába küldendő munka esetében párosítsa a PDFiumPas strukturális ellenőrzését egy dedikált PDF/X preflight motorral és egy tesztnyomtatással, ugyanúgy, ahogyan bármely más megfelelőségi állítást ellenőrizne. A strukturális réteg elkapja azokat a hibákat, amelyek csendben megtörik a RIP gyorsítótárazást; ez egy teljes ellenőrzés fele, nem pedig az egésze
Ha ezeket az ellenőrzéseket egy szélesebb kiadási kapuba építi be, ugyanaz a bájtszintű szkennelési megközelítés támasztja alá a könyvtár egyéb szabványos munkáit, beleértve az objektum- és kereszthivatkozási folyamok érvényesítését még a preflight előtt, valamint a Form XObjects formátumú újrahasznosítható oldalbélyegzők mögötti megosztott objektum fegyelmet, amely eleve RIP-baráttá teszi a dokumentumot. Az itt leírt PDF/VT és PDF/X mentési és ellenőrzési API-k a Delphihez és C++Builderhez készült PDFium VCL komponens részét képezik, amelynek termékoldala a teljes megfelelőségi referenciát tartalmazza