PDF/R, standardizat ca ISO 23504-1, este profilul PDF pentru documente scanate: fiecare pagină poartă exact o singură imagine-fâșie și nimic altceva. PDFium Component îl validează din Delphi, Lazarus și C++Builder prin ValidatePdfRCompliance, care citește un flux și returnează nivelul de conformanță plus un set de probleme concrete
Profilul există deoarece scannerele și sistemele de captură de documente aveau nevoie de o țintă mai îngustă decât PDF/A. Un PDF de arhivă poate conține orice permite partea; un PDF raster este intenționat sărăcit, astfel încât orice cititor conform îl poate afișa identic și orice scriitor conform îl poate produce dintr-o scanare fără un motor de autorie
Ce interzice PDF/R ce permite PDF/A?
Textul, în practică. O pagină raster poartă imaginea scanată și nimic altceva, astfel încât o resursă de font pe o pagină este o încălcare — raportată ca pvriFontForbidden sub ISO 23504-1 §6.5.2. Asta îi surprinde pe cei care adaugă un strat de text OCR invizibil pentru căutare, un lucru normal și util într-un flux PDF/A, dar pur și simplu nu este PDF/R
Relația pagină-imagine este la fel de strictă. §6.5.1 face fiecare pagină exact o singură imagine-fâșie, astfel încât pvriPageImageMismatch se declanșează când numărul de imagini nu se potrivește cu numărul de pagini — o pagină fără imagine și una cu două sunt ambele neconforme. Iar pvriBadMediaBox raportează o pagină a cărei MediaBox nu are forma [0 0 w h] (§6.5.3), deoarece o scanare nu are motiv să stea la o origine cu offset
uses FPdfPdfr;
var
Src: TFileStream;
Res: TPdfRValidationResult;
begin
Src := TFileStream.Create('scan-batch-0142.pdf', fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfRCompliance(Src);
if Res.IsCompliant then
Memo1.Lines.Add('PDF/R-1 conformant')
else
begin
if pvriFontForbidden in Res.Issues then
Memo1.Lines.Add('A page names a font resource; a raster page carries no text');
if pvriPageImageMismatch in Res.Issues then
Memo1.Lines.Add('Image count does not match page count');
if pvriForbiddenImageFilter in Res.Issues then
Memo1.Lines.Add('A strip image uses an encoding outside the white list');
end;
finally
Src.Free;
end;
end;
Ce codări de imagine sunt permise
Patru, iar lista albă este scurtă dintr-un motiv. §6.6 admite /CCITTFaxDecode, /DCTDecode, /JPXDecode și /FlateDecode — fax bivalent, JPEG, JPEG 2000 și deflate fără pierderi, care printre ele acoperă fiecare ieșire de scanner care contează. Orice altceva este raportat ca pvriForbiddenImageFilter, inclusiv /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode și /Crypt
Două dintre acele respingeri merită înțelese mai degrabă decât memorate. /JBIG2Decode comprimǎ scanările bivalente extrem de bine și este perfect legal în PDF/A, dar reconstrucția dicționarului de simboluri poate substitui glife vizual similare — un mod de eșec documentat pentru cifre scanate — iar un profil al cărui întreg scop este reproducerea raster fidelă nu poate admite acel risc. Filtrele ASCII sunt excluse din motiv opus: ele inflatează fișierul fără să adauge ceva de care are nevoie un profil raster
Reguli de structură care se declanșează înainte ca orice pagină să fie citită
PDF/R constrânge și containerul. pvriObjStmPresent raportează un flux /Type /ObjStm, pe care profilul îl interzice complet — fluxurile de obiecte complică analiza simplă, secvențială pe care un cititor raster ar trebui să o poată executa. pvriBadHeader raportează un antet în afara %PDF-1.4 până 1.7 și %PDF-2.0, iar pvriEncryptVersionMismatch raportează un fișier criptat al cărui antet nu este %PDF-2.0, per §6.2.3
Catalogul și dicționarul Info sunt pe listă albă, nu doar verificate. pvriProhibitedCatalogEntry și pvriProhibitedInfoEntry se declanșează pentru intrări în afara setului permis, iar pvriInfoXmpMismatch se declanșează când o intrare Info nu este de acord cu echivalentul său XMP. Un flux /Metadata lipsă al catalogului, un /ID de trailer lipsă și un marcaj de subsol %PDF-raster-1.0 absent au fiecare propria lor problemă
De ce omite înregistrarea opțiunilor de salvare Title și Author
TPdfRSaveOptions poartă Creator, Producer, CreationDate, ModDate, DocumentId și InstanceId, iar în mod deliberat nu are niciun câmp pentru Title, Author, Subject sau Keywords. Acelea patru sunt intrările pe care §6.4.3 le interzice, astfel încât o înregistrare care le-ar expune ar invita apelanții să scrie un fișier neconform printr-un API conform
Două opțiuni booleene controlează curățarea la convertirea unui PDF existent. StripInfoOptionalEntries este implicit True și elimină Title, Author, Subject, Keywords și Trapped din dicționarul Info sursă. StripCatalogOptionalEntries este de asemenea implicit True și elimină Names, Outlines, StructTreeRoot, OutputIntents, Lang și restul, lăsând doar lista albă §6.3. Setați oricare la False și păstrați intrările — și pierdeți conformanța, ceea ce ocazional este exact ce vrea cu adevărat un apelant pentru un fișier intern
var
Opts: TPdfRSaveOptions;
Src, Dest: TFileStream;
begin
Opts := TPdfRSaveOptions.Default;
Opts.Creator := 'Capture Station 4';
Opts.Producer := 'PDFium Component';
Src := TFileStream.Create('scan-in.pdf', fmOpenRead or fmShareDenyWrite);
try
Dest := TFileStream.Create('scan-pdfr.pdf', fmCreate);
try
InjectPdfRMarkers(Src, Dest, Opts); // markers + metadata, not page content
finally
Dest.Free;
end;
finally
Src.Free;
end;
end;
Rețineți ce nu face injecția de markere: adaugă metadate și identificare, dar nu poate furniza conținut de pagină. O pagină sursă care nu poartă nicio imagine-fâșie va eșua încă pvriPageImageMismatch după injecție, deoarece imaginea lipsă nu a fost niciodată o problemă de metadate
Unde se încadrează PDF/R într-un flux de captură
Folosiți-l acolo unde livrabila este scanarea înseși și fidelitatea este întregul contract — imagistică probatorie, captură de cecuri și remitențe, arhive de desene inginerești de la un scanner de format mare. Folosiți PDF/A în schimb în momentul în care documentul are nevoie de text căutabil, marcare, atașamente încorporate sau orice altceva ce stripuiește profilul raster
Un aranjament comun și funcțional este să produceți ambele: un PDF/R original care nu se schimbă niciodată, și un derivat PDF/A cu un strat OCR pentru regăsire. Validatorii sunt independenți, astfel încât aceeași sarcină de lot poate verifica fiecare artefact contra profilului pe care îl revendică efectiv. Pentru partea de arhivare a acelei perechi, vedeți notele despre conformanța de arhivare PDF/A și validarea de preflight PDF/A, iar pentru ieșirea orientată pe tipar prezentarea detaliată despre validarea documentelor PDF/X gata de tipar
PDFium Component aduce motorul PDFium la Delphi, C++Builder și Lazarus cu un API VCL și validatori de conformanță pentru PDF/A, PDF/X, PDF/E, PDF/UA și PDF/R — pagina produsului PDFium Component listează standardele suportate și versiunile de IDE