Το PDF/R, τυποποιημένο ως ISO 23504-1, είναι το προφίλ PDF για σαρωμένα έγγραφα: κάθε σελίδα φέρει ακριβώς μία εικόνα λωρίδας και τίποτα άλλο. Το PDFium Component το επικυρώνει από Delphi, Lazarus και C++Builder μέσω της ValidatePdfRCompliance, που διαβάζει ένα stream και επιστρέφει το επίπεδο συμμόρφωσης συν ένα σύνολο συγκεκριμένων θεμάτων
Το προφίλ υπάρχει επειδή οι σαρωτές και τα συστήματα σύλληψης εγγράφων χρειάζονταν έναν στόχο πιο στενό από το PDF/A. Ένα αρχειακό PDF μπορεί να περιέχει ό,τι επιτρέπει το μέρος· ένα raster PDF είναι σκόπιμα φτωχο, ώστε κάθε συμμορφούμενος αναγνώστης να μπορεί να το εμφανίσει πανομοιότυπα και κάθε συμμορφούμενος συγγραφέας να μπορεί να το παράγει από μια σάρωση χωρίς μηχανή συγγραφής
Τι απαγορεύει το PDF/R που επιτρέπει το PDF/A;
Κείμενο, στην πράξη. Μια raster σελίδα φέρει τη σαρωμένη εικόνα και τίποτα άλλο, οπότε ένας πόρος γραμματοσειράς σε μια σελίδα είναι παραβίαση — αναφέρεται ως pvriFontForbidden υπό ISO 23504-1 §6.5.2. Αυτό εκπλήσσει όσους προσθέτουν μια αόρατη στοίβα κειμένου OCR για δυνατότητα αναζήτησης, που είναι ένα φυσιολογικό και χρήσιμο πράγμα να κάνει σε μια ροή εργασίας PDF/A και απλώς δεν είναι PDF/R
Η σχέση σελίδας-προς-εικόνα είναι εξίσου αυστηρή. Το §6.5.1 κάνει κάθε σελίδα ακριβώς μία εικόνα λωρίδας, οπότε η pvriPageImageMismatch εκπυρσοκροτεί όταν ο αριθμός εικόνων δεν ταιριάζει με τον αριθμό σελίδων — μια σελίδα χωρίς εικόνα και μια σελίδα με δύο είναι και οι δύο μη συμμορφούμενες. Και η pvriBadMediaBox αναφέρει μια σελίδα της οποίας το MediaBox δεν έχει τη μορφή [0 0 w h] (§6.5.3), επειδή μια σάρωση δεν έχει λόγο να κάθεται σε μια μετατοπισμένη αρχή
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;
Ποιες κωδικοποιήσεις εικόνας επιτρέπονται
Τέσσερις, και η λευκή λίστα είναι σύντομη για έναν λόγο. Το §6.6 παραδέχεται /CCITTFaxDecode, /DCTDecode, /JPXDecode και /FlateDecode — δικισμοι bilevel fax, JPEG, JPEG 2000 και lossless deflate, που μεταξύ τους καλύπτουν κάθε έξοδο σαρωτή που έχει σημασία. Όλα τα άλλα αναφέρονται ως pvriForbiddenImageFilter, συμπεριλαμβανομένων /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode και /Crypt
Δύο από αυτές τις απορρίψεις αξίζει να κατανοήσετε παρά να αποστηθίσετε. Η /JBIG2Decode συμπιέζει τις bilevel σαρώσεις εξαιρετικά καλά και είναι απολύτως νόμιμη στο PDF/A, αλλά η ανακατασκευή του λεξικού συμβόλων της μπορεί να υποκαταστήσει οπτικά παρόμοιες γλυφές — ένα τεκμηριωμένο λειτουργικό σφάλμα για σαρωμένα ψηφία — και ένα προφίλ του οποίου ολόκληρος ο σκοπός είναι η πιστή raster αναπαραγωγή δεν μπορεί να παραδεχτεί αυτόν τον κίνδυνο. Τα φίλτρα ASCII αποκλείονται για τον αντίθετο λόγο: διογκώνουν το αρχείο χωρίς να προσθέσουν τίποτα που χρειάζεται ένα raster προφίλ
Κανόνες δομής που εκπυρσοκροτούν πριν διαβαστεί οποιαδήποτε σελίδα
Το PDF/R περιορίζει και το περιέκτη. Η pvriObjStmPresent αναφέρει ένα stream /Type /ObjStm, που το προφίλ απαγορεύει εξ ολοκλήρου — τα object streams περιπλέκουν την απλή, διαδοχική ανάλυση που ένας raster αναγνώστης πρέπει να μπορεί να εκτελέσει. Η pvriBadHeader αναφέρει μια κεφαλίδα εκτός %PDF-1.4 έως 1.7 και %PDF-2.0, και η pvriEncryptVersionMismatch αναφέρει ένα κρυπτογραφημένο αρχείο του οποίου η κεφαλίδα δεν είναι %PDF-2.0, ανά §6.2.3
Ο κατάλογος και το λεξικό Info είναι σε λευκή λίστα, όχι απλώς ελεγχόμενα. Οι pvriProhibitedCatalogEntry και pvriProhibitedInfoEntry εκπυρσοκροτούν για καταχωρήσεις εκτός του επιτρεπόμενου συνόλου, και η pvriInfoXmpMismatch εκπυρσοκροτεί όταν μια καταχώριση Info διαφωνεί με το XMP ισοδύναμό της. Ένα λείπον stream /Metadata καταλόγου, ένα λείπον /ID trailer και μια απόντων δείκτης υποσέλιδου %PDF-raster-1.0 έχουν το δικό τους θέμα το καθένα
Γιατί η εγγραφή επιλογών αποθήκευσης παραλείπει Title και Author
Η TPdfRSaveOptions φέρει Creator, Producer, CreationDate, ModDate, DocumentId και InstanceId, και σκόπιμα δεν έχει πεδίο για Title, Author, Subject ή Keywords. Αυτές οι τέσσερις είναι οι καταχωρήσεις που απαγορεύει το §6.4.3, οπότε μια εγγραφή που θα τις εξέθετε θα προσκαλούσε καλούντες να γράψουν ένα μη συμμορφούμενο αρχείο μέσω ενός συμμορφούμενου API
Δύο boolean επιλογές ελέγχουν τον καθαρισμό κατά τη μετατροπή ενός υπάρχοντος PDF. Η StripInfoOptionalEntries έχει προεπιλογή True και αφαιρεί Title, Author, Subject, Keywords και Trapped από το λεξικό Info της πηγής. Η StripCatalogOptionalEntries επίσης έχει προεπιλογή True και αφαιρεί Names, Outlines, StructTreeRoot, OutputIntents, Lang και τα υπόλοιπα, αφήνοντας μόνο τη λευκή λίστα του §6.3. Ορίστε κάποια σε False και κρατάτε τις καταχωρήσεις — και χάνετε τη συμμόρφωση, που είναι περιστασιακά αυτό που ένας καλών πραγματικά θέλει για ένα εσωτερικό αρχείο
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;
Σημειώστε τι δεν κάνει η ένεση marker: προσθέτει μεταδεδομένα και αναγνωριστικά, και δεν μπορεί να παρασχέσει περιεχόμενο σελίδας. Μια σελίδα πηγής που δεν φέρει εικόνα λωρίδας θα εξακολουθήσει να αποτυγχάνει στην pvriPageImageMismatch μετά την ένεση, επειδή η λείπουσα εικόνα δεν ήταν ποτέ πρόβλημα μεταδεδομένων
Πού χωράει το PDF/R σε μια γραμμή παραγωγής σύλληψης
Χρησιμοποιήστε το όταν το παραδοτέο είναι η ίδια η σάρωση και η πιστότητα είναι ολόκληρο το συμβόλαιο — αποδεικτική απεικόνιση, σύλληψη επιταγών και αποδείξεων, αρχειακά μηχανικών σχεδίων από έναν σαρωτή μεγάλου φορμάτ. Χρησιμοποιήστε PDF/A αντί γι αυτό τη στιγμή που το έγγραφο χρειάζεται αναζητήσιμο κείμενο, επισήμανση, ενσωματωμένα συνημμένα ή οτιδήποτε άλλο απογυμνώνει το raster προφίλ
Μια κοινή και λειτουργική διευθέτηση είναι να παράγετε και τα δύο: ένα PDF/R πρωτότυπο που δεν αλλάζει ποτέ, και ένα PDF/A παράγωγο με στοίβα OCR για ανάκτηση. Οι validators είναι ανεξάρτητοι, οπότε η ίδια εργασία παρτίδας μπορεί να ελέγξει κάθε τεχνούργημα έναντι του προφίλ που πραγματικά διεκδικεί. Για την αρχειακή πλευρά αυτού του ζευγαριού, δείτε τις σημειώσεις για την αρχειακή συμμόρφωση PDF/A και την επικύρωση preflight PDF/A, και για έξοδο προσανατολισμένη στην εκτύπωση την ανάλυση της επικύρωσης εγγράφων PDF/X έτοιμων για εκτύπωση
Το PDFium Component φέρνει τη μηχανή PDFium σε Delphi, C++Builder και Lazarus με ένα VCL API και validator συμμόρφωσης για PDF/A, PDF/X, PDF/E, PDF/UA και PDF/R — η σελίδα προϊόντος PDFium Component παραθέτει τα υποστηριζόμενα πρότυπα και τις εκδόσεις IDE