Štamparija za transakcione poslove vratila vam je seriju izveštaja od 80.000 strana sa odbijanjem u jednoj liniji: "nije PDF/VT, RIP ne može da kešira". Fajl se otvara sasvim normalno u svakom pregledaču na vašem stolu, boje su tačne, podaci su pravilno spojeni. Ništa od toga nije ono što je digitalna presa tražila. Brza varijabilna štampa živi ili umire od toga da presa može da prepozna da je blok sa logotipom klijenta na strani 1 bajt-po-bajt isti objekat kao onaj na strani 40.000, da ga jednom izrenderuje i ponovo iskoristi. PDF/VT je standard koji tu tvrdnju čini mašinski proverljivom, a "izgleda ispravno" je upravo zamka, jer je struktura koju RIP čita nevidljiva na ekranu
PDFiumPas tu strukturu izlaže kroz mali sloj na TPdf: SaveAsPdfVT upisuje je, ValidatePdfVT je proverava. Ovaj članak govori o tome šta te dve metode zaista upisuju na disk i pregledaju, gde je ISO 16612-2 stroži nego što na prvi pogled deluje, i koji delovi predstavljaju poštene strukturne ankere, a ne pun preflight koji možete da fakturišete klijentu
Šta PDF/VT standardizuje i zašto PDF/X ide prvi
PDF/VT (ISO 16612-2:2010) nije novi format fajla. To je sloj metapodataka za optimizaciju naljubljen na PDF/X fajl, i taj redosled je presudan. Standard definiše tri nivoa usklađenosti, ali samo dva od njih imenuju PDF fajl: PDF/VT-1, jedan samostalni dokument, i PDF/VT-2, model skupova fajlova gde stranice referenciraju zajedničke spoljne resurse. Treći token koji možete da vidite, PDF/VT-2s, uopšte nije vrednost na nivou fajla; on živi u MIME zaglavlju toka opisanom u Aneksu A. Ako naiđete na kod koji upisuje GTS_PDFVTVersion = "PDF/VT-2s" u XMP dokumenta, taj kod je pogrešan
Nezaobilazno pravilo za jedan fajl je PDF/X baza. ISO 16612-2 §6.2.1 zahteva da svaki PDF/VT-1 fajl bude i važeći PDF/X-4 fajl. Skup fajlova PDF/VT-2, po §6.2.2, mora umesto toga da sedi na PDF/X-4p, PDF/X-5g ili PDF/X-5pg. Zato pisac PDF/VT ne može samo da doda par identifikacionih ključeva: mora da ponese i ceo skup PDF/X-4 markera, što znači OutputIntent, ugrađeni ICC profil odredišta, odgovarajuće XMP i Info unose dokumenta, trailer /ID, i bez šifrovanja. Preskočite bilo šta od toga i dobićete fajl koji tvrdi da je PDF/VT, a pada u trenutku kada usklađeni potrošač proveri bazu. PDFiumPas tretira PDF/X-4 sloj kao deo PDF/VT snimanja, pa ne pozivate posebni SaveAsPdfX prvo; injektor upisuje oba sloja u jednom prolazu
Upis fajla pomoću SaveAsPdfVT
Minimalni poziv ne traži ništa osim aktivnog dokumenta, jer TPdfVTSaveOptions.Default isporučuje ugrađeni sRGB ICC profil i usklađenost pvc1. Snimanje interno ide kroz tri koraka: uklanja svaku zaštitu (ubacivanje običnih markera u šifrovani object stream bi ga pokvarilo), povezuje postojeći Info rečnik dokumenta i trailer /ID u skup markera tako da se XMP i Info vrednosti poklapaju, a zatim dodaje PDF/X-4 i PDF/VT objekte kroz inkrementalno ažuriranje
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;
Za stvarni produkcioni izlaz gotovo uvek želite da zamenite OutputIntent karakterizacijom svoje prese, a ne generičkim sRGB padom. Prosledite ICC bajtove i identifikatore uslova kroz TPdfVTSaveOptions:
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;
Jedan detalj u tom isečku je namerna zaštitna ograda, a ne ograničenje sa kojim možete da se prepirete. Podešavanje Opt.Conformance := pvc2 ne proizvodi PDF/VT-2 fajl. Pisac normalizuje svaki zahtev koji nije pvc1 nazad u pvc1, jer je PDF/VT-2 format skupa fajlova, a pisac za jedan fajl koji dodaje jedan izlazni dokument fizički ne može da sastavi skup spoljašnjih resursa koji §6.2.2 traži. Vrednost pvc2 postoji za putanju čitanja, tako da ValidatePdfVT može da prepozna i prijavi postojeći dokument skupa fajlova; to nije cilj upisa
DPart stablo: strukturirajte ono što RIP zaista čita
Srce PDF/VT-a je Document Part (DPart) hijerarhija. Ona omogućava presi da dugačak tiraž podeli na zapise, zapise grupiše u primaoce ili poštanske pakete, i doda Document Part Metadata tako da nizvodna oprema može da usmeri i fakturiše svaki komad. ISO 16612-2 §6.5 opisuje povezivanje: katalog nosi /DPartRoot, koreni DPart čvor nosi /DPartRootNode i /NodeNameList koji imenuje svaki nivo hijerarhije, list DPart-ovi pokrivaju opsege stabla stranica, a svaka stranica koja pripada nekom delu pokazuje nazad na svoj list preko unosa /DPart
Kada vaš izvorni dokument već sadrži upotrebljivu hijerarhiju, SaveAsPdfVT je čuva. Kada je nema, pisac sintetiše minimalnu: jedan DPart na nivou dokumenta koji obuhvata trenutno stablo stranica redom, sa /DPart povratnom vezom dodatom svakom aktivnom objektu strane i jednim nivoom /NodeNameList [/Document]. Budite pošteni prema sebi oko toga šta je to minimalno stablo. To je strukturni anker koji zadovoljava zahteve oblika iz §6.5; to nije poslovni metapodatak. Ne može da izmisli primaoce, granice poštanske jedinice ili serije proizvoda, jer te informacije nikada nisu bile u izvoru. Ako imate podatke po primaocu, očekuje se da sami izgradite dublje DPart stablo i proširite /NodeNameList tako da odgovara nivoima koje kreirate
Validacija koja ide dalje od same prisutnosti ključeva
ValidatePdfVT vraća TPdfVTValidationResult zapis sa tri stvari: otkriveni Conformance, skup Issues i IsCompliant pomoćni flag koji je tačan samo kada je usklađenost stvarni nivo i skup problema prazan. Enumeracija problema je namerno precizna, pa neuspešan rezultat govori koju ste klauzulu promašili umesto samo "neispravno":
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;
Dve provere koje vredi dubinski razumeti su uparivanje usklađenosti i DPart obilazak, jer su obe nekada bile previše blage i kasnije zategnute da prate specifikaciju. Na strani uparivanja, validator radi tačno poklapanje, ne "bilo koji PDF/X može": PDF/VT-1 fajl se prihvata samo na PDF/X-4 PDF/X-4 PDF/X-4p, PDF/X-5g, ili PDF/X-5pg. Marker PDF/VT-1 postavljen na PDF/X-1a bazu prijavljuje se, ne propušta se
DPart obilazak je mesto gde živi većina strogoće. Nije dovoljno da katalog ima /DPartRoot ključ, jer lažni prazan objekat ili onaj bez veza ka stranicama i dalje ne može da se potroši. HasValidDPartHierarchyProvere ValidateDPartNode i rekurzivni /Start prolaze celu strukturu: prate roditeljske veze, odbacuju duplu decu i cikluse, obezbeđuju da su /DParts i /DPart međusobno isključivi, i zahtevaju da opsezi list stranica pokriju stablo stranica u redosledu dubine prvo, pri čemu svaka stranica pokazuje na list koji je sadrži. Sve te unutrašnje greške se sabijaju u jedan pvviMissingDPartRoot bit problema umesto da proširuju javnu enumeraciju, pa taj jedan flag tumačite kao "DPart hijerarhija je neupotrebljiva", a ne doslovno kao "root ključ nedostaje"
Tri sintaktičke zamke koje validator sada primenjuje
Uzastopni prolazi kroz §6.5 Tabelu 4 otkrili su oblike koje su starije verzije prihvatale, ali standard ne. To su upravo one stvari koje ručno građeno DPart stablo često pogreši, pa ih vredi izričito pomenuti:
/DPartsje niz nizova, a ne ravan niz. Svaki element spoljnog niza mora i sam biti niz indirektne reference. Ravan/DParts [9 0 R]se odbacuje; usklađeni oblik je/DParts [[9 0 R] [10 0 R]]/EndTime se sprečava da nestrukturisana hijerarhija glumi važeći nivo. označava samo stvarni višestranični opseg./EndList DPart može da nosi/Startsamo kada ima i/End, a/Startmora da bude kasnije od/Start 3 0 R /End 3 0 Ru redosledu stabla stranica. Degenerisan/NodeNameListsada čini hijerarhiju neupotrebljivom umesto da se čita kao jednostranični deo. nazivi moraju da prežive PDF name unescaping kao XML NMTOKEN-ovi./Bad#20NameNaziv kao.,-,_,:, plus non-ASCII bytes) that catches whitespace and delimiter mistakes without rejecting legitimate localized or vendor-specific names
XMP markeri: dva načina da se upiše isto svojstvo
PDF/VT identifikacija živi u XMP-u pod pdfvtid prostorom imena, konkretno GTS_PDFVTVersion i GTS_PDFVTModDate, zajedno sa standardnim xmp:CreateDate i xmp:ModifyDate. Suptilnost koja kod naivnih čitača izaziva lažne prijave "nedostaje" jeste da se bilo šta od ovoga može serijalizovati na dva načina: kao tekst elementa (<pdfvtid:GTS_PDFVTVersion>PDF/VT-1</pdfvtid:GTS_PDFVTVersion>) ili kao RDF atribut na elementu opisa. PDFiumPas čita oba oblika, pa fajl koji je drugi alat upisao u atributnom stilu nije kažnjen. On takođe sprovodi pravilo doslednosti iz §6.3 da GTS_PDFVTModDate mora biti jednako xmp:ModifyDate; neslaganje podiže pvviModDateMismatch
Još jedno pravilo iz iste klauzule: nepoznata GTS_PDFVTVersion vrednost se čuva kao pvcUnknown umesto da se vraća nazad u pvcNone. Ta razlika je operativno važna. pvcNone znači "nema PDF/VT markera uopšte, običan PDF", dok pvcUnknown znači "nešto je označeno verzijom koju ovaj validator ne prepoznaje" (među njima i PDF/VT-2s slučaj). Mešanje ta dva bi sakrilo oštećen fajl u istoj fioci kao i običan dokument
Gde garancija prestaje
Važno je precizno odrediti granicu onoga što ove metode obećavaju, jer varijabilna štampa nosi stvaran novac. DPart i provere uparenosti su strukturna validacija na nivou bajta. One potvrđuju da su prisutni i međusobno dosledni skelet optimizacije, PDF/X-4 bazni markeri, OutputIntent i XMP. To nije PDF/X-4 preflight na nivou sadržaja: ne proveravaju da li je svaka boja unutar deklarisanog uslova izlaza, da li su svi fontovi ugrađeni ili da li je ušla neka zabranjena ivica transparentnosti i mešanja. Za posao koji ide na ugovornu presu, uparite strukturnu validaciju PDFiumPas-a sa posebnim PDF/X preflight engine-om i probnim otiskom, isto kao što biste proverili bilo koju drugu tvrdnju o usklađenosti. Strukturni sloj hvata greške koje tiho razbijaju RIP keširanje; to je jedna polovina potpune provere, ne cela stvar
Ako ove provere ugrađujete u širi release gate, isti pristup skeniranja na nivou bajta stoji iza drugih standardnih poslova biblioteke, uključujući validaciju object i cross-reference stream-ova pre nego što fajl ikada stigne do preflight-a, i disciplinu zajedničkih objekata iza ponovo upotrebljivih pečata stranica sa Form XObjects koja dokument čini prijemčivim za RIP od samog početka. API-je za snimanje i validaciju PDF/VT i PDF/X opisane ovde dobijate uz PDFium VCL komponentu za Delphi i C++Builder, čija stranica proizvoda nosi punu referencu usklađenosti