Transakčná tlačiareň vám vráti 80 000-stranový beh výpisov s jednovetovým odmietnutím: „not PDF/VT, RIP cannot cache“. Súbor sa na každom prehliadači na stole otvorí správne, farby sú v poriadku a dáta sa zlúčili korektne. Presne to však digitálny tlačový stroj nechcel. Vysokorýchlostná variable-data tlač stojí a padá na tom, či tlačový RIP dokáže rozpoznať, že blok s logom zákazníka na strane 1 je bajt po bajte ten istý objekt ako na strane 40 000, vyrenderovať ho raz a znovu použiť. PDF/VT je štandard, ktorý tento sľub robí strojovo kontrolovateľným, a práve „vyzerá to správne“ je pasca, pretože štruktúra, ktorú RIP číta, je na obrazovke neviditeľná
PDFiumPas túto štruktúru sprístupňuje cez malý povrch na TPdf: SaveAsPdfVT writes it, ValidatePdfVT. Tento článok vysvetľuje, čo tieto dve metódy skutočne zapisujú na disk a čo kontrolujú, v čom je ISO 16612-2 prísnejšie, než sa na prvý pohľad zdá, a ktoré časti sú poctivé štrukturálne kotvy namiesto plného preflightu, ktorý by ste mohli fakturovať klientovi
Čo PDF/VT štandardizuje a prečo musí najprv prísť PDF/X
PDF/VT nie je nový formát súboru. Je to vrstva optimalizačných metadát priskrutkovaná na PDF/X súbor a toto poradie nesie váhu. Štandard definuje tri úrovne zhody, ale iba dve z nich pomenúvajú PDF súbor: PDF/VT-1, samostatný dokument, a PDF/VT-2, model file setu, v ktorom strany odkazujú na zdieľané externé zdroje. Tretí token, s ktorým sa môžete stretnúť, PDF/VT-2s, is not a file-level value at all; it lives in a MIME stream header described in Annex A. If you find code stamping GTS_PDFVTVersion = "PDF/VT-2s" into a document's XMP, that code is wrong
, vôbec nie je hodnota na úrovni súboru, ale hodnota v MIME stream headeri. Ak nájdete kód, ktorý zapisuje /ID do XMP dokumentu, taký kód je nesprávny.SaveAsPdfXNeobídateľné pravidlo pre samostatný súbor je základ PDF/X. ISO 16612-2 vyžaduje, aby každý PDF/VT-1 súbor bol zároveň platný PDF/X-4. Preto writer PDF/VT nemôže iba pripojiť pár identifikačných kľúčov. Musí so sebou niesť celý markerový set PDF/X-4, teda OutputIntent, vložený ICC destination profile, zodpovedajúce záznamy v XMP a Info, trailer
a žiadne šifrovanie. Ak čokoľvek z toho vynecháte, máte súbor, ktorý tvrdí PDF/VT a zlyhá v okamihu, keď kompatibilný konzument skontroluje jeho základ. PDFiumPas považuje vrstvu PDF/X-4 za súčasť ukladania PDF/VT, preto najprv nevoláte samostatné
; injektor zapisuje obe vrstvy v jednom prechode.TPdfVTSaveOptions.DefaultZápis súboru pomocou SaveAsPdfVTpvc1Minimálne volanie nepotrebuje nič viac než aktívny dokument, pretože /ID into the marker set so the XMP and Info values agree, then it appends the PDF/X-4 and PDF/VT objects through an incremental update
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;
For real production output you almost always want to override the OutputIntent with your press's characterization, not the generic sRGB fallback. Supply the ICC bytes and the condition identifiers through TPdfVTSaveOptions do markerovej sady tak, aby hodnoty v XMP aj Info súhlasili, a potom pripojí PDF/X-4 aj PDF/VT objekty cez inkrementálnu aktualizáciu
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; // pvc2 is normalised to pvc1 on write
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;
Pri reálnom produkčnom výstupe takmer vždy chcete prepísať OutputIntent vlastnou charakteristikou tlačového stroja, nie všeobecným fallbackom sRGB. ICC bajty a identifikátory podmienok odovzdajte cez Opt.Conformance := pvc2 does not produce a PDF/VT-2 file. The writer normalizes any non-pvc1Jeden detail v tomto snippete je zámerná ochranná lišta, nie obmedzenie, o ktorom sa dá polemizovať. Nastavenie pvc1, because PDF/VT-2 is a file-set format and a single-file writer that appends one output document physically cannot assemble the external resource set §6.2.2 demands. The pvc2 value exists for the read path, so ValidatePdfVT can recognize and report an existing file-set document; it is not a write target
existuje pre read path, aby
vedelo rozpoznať a nahlásiť existujúci file-set dokument; nie je to cieľ zapisovania./DPartRootDPart strom: štruktúra, ktorú RIP skutočne číta/DPartRootNodeSrdcom PDF/VT je hierarchia Document Part, teda DPart. Umožňuje tlačovému stroju rozdeliť dlhý beh na záznamy, zoskupiť ich do príjemcov alebo poštových balíkov a pripojiť Document Part Metadata tak, aby downstream zariadenia vedeli smerovať a účtovať každý kus. ISO 16612-2 opisuje zapojenie takto: katalóg nesie /NodeNameList naming each hierarchy level, leaf DParts cover ranges of the page tree, and every page that belongs to a part points back at its leaf through a page-level /DPart položku
Keď už zdrojový dokument použiteľnú hierarchiu obsahuje, SaveAsPdfVT preserves it. When it does not, the writer synthesizes a minimal one: a single document-level DPart that spans the current page tree in order, with a /DPart back-reference appended to each live page object and a one-level /NodeNameList [/Document]. Be honest with yourself about what that minimal tree is. It is a structural anchor that satisfies §6.5's shape requirements; it is not business metadata. It cannot invent recipients, mail-piece boundaries, or product batches, because that information was never in the source. If you have per-recipient data, you are expected to build a deeper DPart tree yourself and extend the /NodeNameList zachová. Keď ju neobsahuje, writer syntetizuje minimálnu verziu: jediný document-level DPart, ktorý v poradí pokrýva aktuálny strom strán, so spätným odkazom
pripojeným ku každej živej page object a jednolayerovým
ValidatePdfVT. Buďte k sebe úprimní, čo taký minimálny strom predstavuje. Je to štrukturálna kotva, ktorá spĺňa tvarové požiadavky normy. Nie sú to business metadáta. Nedokáže vymyslieť príjemcov, hranice zásielok ani produktové dávky, pretože tieto informácie v zdroji nikdy neboli. Ak máte dáta po príjemcoch, očakáva sa, že hlbší DPart strom vytvoríte sami a rozšírite TPdfVTValidationResult tak, aby zodpovedal úrovniam, ktoré vytvoríte.ConformanceValidácia, ktorá ide ďalej než len k prítomnosti kľúčovIssues, and an IsCompliant vracia záznam
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;
The two checks worth understanding in depth are the conformance pairing and the DPart walk, because both used to be too lenient and were tightened to match the spec. On the pairing side, the validator does exact matching, not "any PDF/X will do": a PDF/VT-1 file is only accepted on a PDF/X-4 base, and a PDF/VT-2 file only on PDF/X-4p, PDF/X-5g, or PDF/X-5pg. A PDF/VT-1 marker sitting on a PDF/X-1a base is reported, not waved through
The DPart walk is where most of the rigor lives. It is not enough for the catalog to have a /DPartRoot key, because a forged empty object or one with no page links still cannot be consumed. HasValidDPartHierarchy and the recursive ValidateDPartNode trace the whole structure: they follow parent links, reject duplicate children and cycles, enforce that /Start and /DParts are mutually exclusive, and require leaf page ranges to cover the page tree in depth-first order with each page's /DPart pointing at the leaf that contains it. All of those internal faults collapse to the single pvviMissingDPartRoot ako issue bit, takže tento príznak čítajte ako „DPart hierarchia je nepoužiteľná“, nie doslova ako „chýba root key“
Tri syntaktické pasce, ktoré validátor teraz vynucuje
Postupné prechody cez tabuľku 4 v §6.5 odhalili tvary, ktoré staršie verzie akceptovali, ale štandard nie. Presne na týchto miestach sa ručne stavaný DPart strom zvykne pokaziť, preto stojí za to ich vypichnúť:
/DPartsje pole polí, nie ploché pole. Each element of the outer array must itself be an indirect-reference array. A flat/DParts [9 0 R]is rejected; the conforming shape is/DParts [[9 0 R] [10 0 R]]. Tým sa zabráni tomu, aby sa nehierarchická štruktúra tvárila ako platná úroveň/Endoznačuje iba skutočný viacstranový rozsah. A leaf DPart may carry/Endonly when it also has/Start, and/Endmust fall later than/Startin page-tree order. A degenerate/Start 3 0 R /End 3 0 Rteraz robí hierarchiu nepoužiteľnou namiesto toho, aby sa čítal ako jednolistový part/NodeNameListnázvy musia po unescapingu PDF mien prežiť ako XML NMTOKEN. Názov ako/Bad#20Namesa rozbalí na hodnotu obsahujúcu medzeru, čo nie je platný token. Implementácia vykonáva ľahkú ASCII kontrolu, takže zachytí whitespace a delimiter chyby bez toho, aby odmietala legitímne lokalizované alebo vendor-specific mená..,-,_,:, plus non-ASCII bytes) that catches whitespace and delimiter mistakes without rejecting legitimate localized or vendor-specific names
Značky XMP: dva spôsoby, ako zapísať tú istú vlastnosť
Identifikácia PDF/VT žije v XMP pod namespace pdfvtid namespace, specifically GTS_PDFVTVersion and GTS_PDFVTModDate, alongside the standard xmp:CreateDate and xmp:ModifyDate. Jemnosť, ktorá v naivných čítačkách spôsobuje falošné hlásenia „missing“, spočíva v tom, že každú z týchto hodnôt možno serializovať dvoma spôsobmi: ako text elementu alebo ako RDF atribút na elemente description. PDFiumPas číta obe podoby, takže súbor, ktorý iný nástroj zapísal atribútovým štýlom, nie je penalizovaný. Zároveň vynucuje pravidlo konzistencie, podľa ktorého <pdfvtid:GTS_PDFVTVersion>PDF/VT-1</pdfvtid:GTS_PDFVTVersion>) or as an RDF attribute on the description element. PDFiumPas reads both forms, so a file that another tool wrote in attribute style is not penalized. It also enforces the §6.3 consistency rule that GTS_PDFVTModDate must equal xmp:ModifyDate; a mismatch raises pvviModDateMismatch
Ešte jedno pravidlo z tej istej časti: neznáma hodnota GTS_PDFVTVersion value is preserved as pvcUnknown rather than being folded back to pvcNone. Tento rozdiel je prevádzkovo dôležitý. pvcNone means "no PDF/VT marker at all, an ordinary PDF," while pvcUnknown means "something stamped a version this validator does not recognize" (the PDF/VT-2s. Zlievanie týchto dvoch stavov by schovalo chybný súbor do toho istého koša ako obyčajný dokument
Kde sa záruka končí
Oplatí sa byť presný v tom, čo tieto metódy sľubujú, pretože zhoda variable-data printu má reálne finančné dôsledky. Kontroly DPart a párovania sú štrukturálna validácia na úrovni bajtov. Potvrdzujú, že optimalizačná kostra, základné markery PDF/X-4, OutputIntent a XMP sú prítomné a interne konzistentné. Nie je to content-level PDF/X-4 preflight: nekontrolujú, či sú všetky farby v deklarovanej output condition, či sú vložené všetky fonty alebo či sa neprepašoval zakázaný edge case s transparentným blendovaním. Pri zákazke, ktorú posielate na zmluvnú tlač, párujte štrukturálnu validáciu PDFiumPas s dedikovaným PDF/X preflight enginom a testovacou tlačou. Štrukturálna vrstva zachytí zlyhania, ktoré ticho rozbijú RIP caching, ale je to len polovica kompletnej kontroly
Ak tieto kontroly vkladáte do širšieho release gate, rovnaký byte-level scanning podkladá aj ďalšie štandardové funkcie knižnice vrátane validating object and cross-reference streams ešte predtým, než súbor dôjde do preflightu, a disciplínu zdieľaných objektov za článkom reusable page stamps with Form XObjects, ktorá z dokumentu vôbec robí niečo, s čím vie RIP efektívne pracovať. API na ukladanie a validáciu PDF/VT a PDF/X opísané tu sú súčasťou PDFium VCL component pre Delphi a C++Builder, ktorého produktová stránka obsahuje plný referenčný opis zhody