Τεχνικό Άρθρο

Έξοδος PDF/A, PDF/X και PDF/UA στο Delphi: Ένας οδηγός για το HotPDF

Τα PDF/A, PDF/X και PDF/UA είναι τρία διαφορετικά πρότυπα που λύνουν τρία διαφορετικά προβλήματα: μακροπρόθεσμη αρχειοθέτηση, ανταλλαγή για εκτύπωση, και προσβασιμότητα. Δεν είναι τρία πλαίσια επιλογής σε μία φόρμα συμμόρφωσης, και το πιο συνηθισμένο λάθος είναι να τα αντιμετωπίζετε σαν να ήταν. Ένα αρχείο μπορεί να είναι άψογο PDF/A και άχρηστο για ένα τυπογραφείο· ένα τέλειο master εκτύπωσης μπορεί να είναι μη αναγνώσιμο από έναν screen reader. Χειρότερα, και τα τρία είναι περιορισμοί στην εσωτερική δομή του αρχείου, όχι στο πώς φαίνεται. Ένα έγγραφο που ανοίγει καθαρά σε κάθε πρόγραμμα προβολής που έχετε μπορεί ακόμη να αποτύχει στην επικύρωση με την πρώτη προσπάθεια, και συνήθως αποτυγχάνει

Το HotPDF, η εγγενής βιβλιοθήκη VCL PDF της losLab, αντιμετωπίζει τη συμμόρφωση ως κάτι που δηλώνετε προτού υπάρξει η πρώτη σελίδα. Ορίζετε μια ιδιότητα συμμόρφωσης, επισυνάπτετε τις δομές που απαιτεί το πρότυπο, και η βιβλιοθήκη αρνείται διαμορφώσεις που έρχονται σε αντίθεση με το προφίλ κατά την αποθήκευση. Αυτό είναι καλύτερο μοντέλο από το να παράγετε ένα αρχείο και να ελπίζετε ότι ένας μετα-επεξεργαστής μπορεί να το αναβαθμίσει εκ των υστέρων, επειδή τα περισσότερα από όσα απαιτούν αυτά τα πρότυπα δεν μπορούν να προστεθούν μετά τα γεγονότα

Τρία πρότυπα ISO, τρεις διαφορετικές υποσχέσεις

Το PDF/A (ISO 19005) αφορά τον χρόνο. Υπόσχεται ότι ένα αρχείο θα αποδίδεται πανομοιότυπα ακόμη και δεκαετίες από τώρα, οπότε απαιτεί πλήρη αυτάρκεια: κάθε γραμματοσειρά ενσωματωμένη, κάθε χρώμα να έχει νόημα ανεξάρτητο από συσκευή μέσω ενός OutputIntent, πλήρη μεταδεδομένα XMP, και απαγόρευση οτιδήποτε η συμπεριφορά του εξαρτάται από το περιβάλλον. Η κρυπτογράφηση και το JavaScript αποκλείονται, επειδή κανείς δεν μπορεί να εγγυηθεί ότι ο αποκρυπτογραφητής ή η μηχανή σεναρίων θα υπάρχουν το 2050

Το PDF/X (ISO 15930) αφορά το χρώμα στο χαρτί. Υπάρχει ώστε ένας σχεδιαστής να μπορεί να παραδώσει ένα αρχείο σε ένα τυπογραφείο χωρίς κανείς από τους δύο να χρειάζεται να το συζητήσει, κάτι που σημαίνει χαρακτηρισμένες συνθήκες εκτύπωσης, ένα υποχρεωτικό κλειδί /Trapped, καθορισμένη γεωμετρία περικοπής και bleed, και, στην παραλλαγή X-1a, καμία ζωντανή διαφάνεια για να μαντέψει το RIP. Το PDF/UA (ISO 14289) αφορά ποιος μπορεί να διαβάσει το αποτέλεσμα. Η τεχνολογία υποβοήθησης χρειάζεται ένα πλήρες δέντρο ετικετών, μια λογική σειρά ανάγνωσης, μια δηλωμένη γλώσσα εγγράφου, και εναλλακτικά κείμενα για οτιδήποτε δεν είναι κείμενο

Επειδή τα τρία τραβούν προς διαφορετικές κατευθύνσεις, επιλέξτε το κυρίαρχο πρότυπο ανά κανάλι εξόδου αντί να κυνηγάτε ένα αρχείο που ικανοποιεί και τα τρία. Ένα master εκτύπωσης μόνο-CMYK είναι ακριβώς το λάθος πράγμα για να δώσετε σε έναν χρήστη screen reader που ποτέ δεν βλέπει χρώμα, και το κλείδωμα του αρχειακού προφίλ στη δυναμική συμπεριφορά συγκρούεται με οτιδήποτε διαδραστικό. Παράγετε ανά κανάλι από τα ίδια δεδομένα πηγής και αποφεύγετε ολόκληρη τη σύγκρουση

Το HotPDF παράγει αρχεία PDF/A, PDF/X και PDF/UA ανά κανάλι εξόδου από ένα έγγραφο πηγής σε Delphi, με κάθε πρότυπο ISO να κρατά διαφορετική δομική υπόσχεση
Το PDF/A, το PDF/X και το PDF/UA τραβούν σε διαφορετικές κατευθύνσεις, οπότε το HotPDF παράγει ένα αρχείο ανά κανάλι εξόδου από την ίδια πηγή

PDF/A: το OutputIntent είναι το κομμάτι που όλοι ξεχνούν

Αν ένα αρχείο PDF/A αποτυγχάνει στην επικύρωση, το OutputIntent είναι το πρώτο πράγμα που πρέπει να ελέγξετε. Είναι η δομή που οι γεννήτριες παραλείπουν πιο συχνά, ακριβώς επειδή τίποτα ορατό δεν εξαρτάται από αυτήν. Το ISO 19005 απαιτεί ένα: ένα ενσωματωμένο προφίλ ICC που καθηλώνει τι σημαίνουν στην πραγματικότητα τα χρώματα συσκευής του εγγράφου. Το HotPDF κάνει αυτό το προφίλ ρητή είσοδο αντί για μεταγενέστερη σκέψη:

var
  Pdf: THotPDF;
  ICC: TFileStream;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'invoice-archival.pdf';
    Pdf.PDFACompliance := 'B';            // επίπεδο B: οπτική πιστότητα
    Pdf.Lang := 'en-US';
    Pdf.StandardFontEmulation := False;   // ενσωμάτωση πραγματικών γραμματοσειρών, χωρίς εξομοίωση Base-14
    ICC := TFileStream.Create('sRGB.icc', fmOpenRead);
    try
      Pdf.AddPDFAOutputIntent('sRGB IEC61966-2.1', '', ICC, 3, 'DeviceRGB');
    finally
      ICC.Free;
    end;
    Pdf.BeginDoc;
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 760, 0, 'Archival invoice body');
    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Μερικές λεπτομέρειες αποφασίζουν εδώ την επιτυχία ή την αποτυχία. Το StandardFontEmulation πρέπει να είναι απενεργοποιημένο: οι εξομοιωμένες γραμματοσειρές Base-14 δεν ενσωματώνονται, και η ενσωμάτωση δεν είναι διαπραγματεύσιμη κατά ISO 19005. Η κρυπτογράφηση πρέπει να παραμένει απενεργοποιημένη, οπότε ποτέ μην συνδυάζετε το PDFACompliance με το ActivateProtection· ένα κρυπτογραφημένο αρχειακό αρχείο είναι μια αντίφαση που ο επικυρωτής εντοπίζει αμέσως. Ο αριθμός components στο AddPDFAOutputIntent πρέπει να ταιριάζει με το προφίλ, που είναι 3 για ένα προφίλ RGB όπως το sRGB IEC61966-2.1 και 4 για CMYK. Το HotPDF παρακολουθεί τη χρήση DeviceRGB και DeviceCMYK έναντι του δηλωμένου intent καθώς γράφει, οπότε ένα αδέσποτο γέμισμα CMYK σε ένα έγγραφο με RGB intent μετατρέπεται σε αναφερόμενο πρόβλημα αντί για σιωπηλό

Ένα πράγμα αξίζει να ειπωθεί για το προφίλ ICC: αντιμετωπίστε το ως ένα εκδοσιοποιημένο τεχνούργημα ανάπτυξης, όχι ως ένα αρχείο που κάποιος κάποτε άφησε στον build server. Τα bytes του ενσωματώνονται σε κάθε έγγραφο που παράγετε, οπότε ένα περικομμένο ή αλλοιωμένο προφίλ δηλητηριάζει σιωπηλά μια ολόκληρη παρτίδα, και το ανακαλύπτετε μόνο κατά την επικύρωση. Παραδώστε το με τον installer σας, καταγράψτε το checksum του στο run log, και φορτώστε το μέσω του μοτίβου TFileStream που φαίνεται παραπάνω ώστε ένα απόν αρχείο να αποτυγχάνει δυνατά κατά τη δημιουργία αντί σιωπηλά στην πύλη αρχειοθέτησης

PDF/X για εκτύπωση: Trapped, CMYK και το προφίλ πιεστηρίου

Τα masters εκτύπωσης αντιστρέφουν την ιστορία του χρώματος. Το πιεστήριο θέλει χαρακτηρισμένο CMYK, και το πρότυπο σας αναγκάζει να δηλώσετε αν έχει εφαρμοστεί trapping ακόμη κι όταν η ειλικρινής απάντηση είναι ότι δεν έχετε ιδέα. Το κλειδί /Trapped είναι υποχρεωτικό ούτως ή άλλως:

Pdf.PDFXCompliance := 'X-1a';
Pdf.Trapped := 'Unknown';        // υποχρεωτικό κλειδί κατά ISO 15930
ICC := TFileStream.Create('FOGRA39.icc', fmOpenRead);
try
  Pdf.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)', '', ICC, 4, 'DeviceCMYK');
finally
  ICC.Free;
end;
Pdf.BeginDoc;
// σχεδιάστε με χρώματα ασφαλή για CMYK, χωρίς διαφάνεια, χωρίς κρυπτογράφηση
Pdf.EndDoc;

Ο αριθμός components είναι τώρα 4 για το προφίλ πιεστηρίου CMYK. Το X-1a απαγορεύει επίσης τη ζωντανή διαφάνεια, οπότε ελέγξτε κάθε κώδικα σχεδίασης που στοιβάζει ημιδιαφανή στοιχεία· ό,τι συνθέτει ένα πρόγραμμα προβολής στην οθόνη είναι ακριβώς αυτό που θα αρνηθεί να ερμηνεύσει ένα RIP. Όταν το τυπογραφείο σας στέλνει διαφορετικό χαρακτηρισμό, αντικαταστήστε τα bytes του προφίλ και τη συμβολοσειρά αναγνωριστικού αλλά αφήστε την γύρω δομή ανέγγιχτη

PDF/UA: η δομή δημιουργείται, ποτέ δεν προστίθεται εκ των υστέρων

Η προσβασιμότητα είναι το πρότυπο που οι ομάδες προσπαθούν πιο συχνά να κολλήσουν στο τέλος, και τιμωρεί αυτή την προσέγγιση πιο σκληρά από τα άλλα δύο. Το δέντρο ετικετών πρέπει να αντικατοπτρίζει τη σειρά με την οποία το περιεχόμενο δημιουργήθηκε λογικά, κάτι που είναι πληροφορία που απλά δεν έχετε πια μόλις γραφτεί το αρχείο. Ο ορισμός του PDFUACompliance ενεργοποιεί την ετικετοποιημένη έξοδο, και το API δομής συνδέει κάθε κλήση σχεδίασης με τον σημασιολογικό της ρόλο καθώς προχωράτε:

Το HotPDF χτίζει ζωντανά το δέντρο ετικετών PDF/UA καθώς εκτελείται κάθε κλήση σχεδίασης Delphi, και κείμενο που εκπέμπεται εκτός BeginTaggedContent και EndTaggedContent μένει αόρατο για screen readers
Το δέντρο ετικετών γράφεται όσο σχεδιάζετε, και κείμενο έξω από ζευγάρι με ετικέτα αποδίδεται κανονικά αλλά μένει αόρατο για αναγνώστες οθόνης
Pdf.PDFUACompliance := True;     // ενεργοποιεί αυτόματα το tagged PDF
Pdf.Lang := 'en-US';             // ορίστε το ρητά· κενό επιστρέφει στο 'en'
Pdf.BeginDoc;

Root := Pdf.AddStructureElement(sstDocument, nil);
H1 := Pdf.EmitTaggedHeading(1, Root, 50, 700, 'Quarterly Report');
Para := Pdf.BeginTaggedContent('P', Root);
Pdf.CurrentPage.TextOut(50, 650, 0, 'Revenue grew in all regions.');
Pdf.EndTaggedContent;

Pdf.EndDoc;

Το σφάλμα που πρέπει να προσέξετε είναι κείμενο σχεδιασμένο έξω από οποιοδήποτε ζεύγος BeginTaggedContent/EndTaggedContent. Αποδίδεται τέλεια και παραμένει αόρατο σε έναν screen reader, οπότε κανένας βλέπων δοκιμαστής δεν το εντοπίζει ποτέ· το σφάλμα κυκλοφορεί και εμφανίζεται μόνο όταν ένας πραγματικός χρήστης τεχνολογίας υποβοήθησης πέφτει στο κενό. Όταν τα templates σας φέρουν προσαρμοσμένα ονόματα ρόλων δομής, αντιστοιχίστε τα στο τυπικό σύνολο με το AddStructRoleMap('MyHead', 'H1') ώστε οι συμμορφούμενοι αναγνώστες να ξέρουν τι σημαίνουν. Το ISO 14289 απαιτεί επίσης δηλωμένη γλώσσα. Το HotPDF επιστρέφει στο 'en' όταν το Lang είναι κενό, αλλά αυτό είναι δίχτυ ασφαλείας, όχι λόγος να αφήσετε τη γλώσσα του πραγματικού εγγράφου χωρίς ορισμό

Επαλήθευση: εμπιστευτείτε τον επικυρωτή, όχι το πρόγραμμα προβολής

Ένα πρόγραμμα προβολής που ανοίγει το αρχείο σας δεν αποδεικνύει τίποτα για τη συμμόρφωση, οπότε η επαλήθευση ανήκει στη διαδρομή κυκλοφορίας με εργαλεία που ελέγχουν δομή αντί για απόδοση. Για PDF/A και PDF/UA, το veraPDF είναι ο ανοιχτός επικυρωτής επιπέδου αναφοράς· αναφέρει αποτυχίες κατά ρήτρα ISO, κάτι που αντιστοιχίζεται κατευθείαν πίσω στη διαμόρφωση παραπάνω. Για PDF/X, τα προφίλ Preflight του Adobe Acrobat εξακολουθούν να είναι ο πρακτικός έλεγχος, επειδή η συμμόρφωση πιεστηρίου αφορά το intent χρώματος εξίσου με τη σύνταξη

Η γεννήτρια κάνει το δικό της μέρος σε αυτό. Κατά την αποθήκευση το HotPDF συμφιλιώνει τις σημαίες χαρακτηριστικών με τη διαμορφωμένη έκδοση PDF, υποβαθμίζοντας σιωπηλά ό,τι η έκδοση δεν μπορεί να εκφράσει, όπως το AES-256 να πέφτει σε AES-128 κάτω από το PDF 1.7. Οι πύλες συμμόρφωσης στο EndDoc πηγαίνουν παραπέρα και εγείρουν εξαίρεση απευθείας σε σκληρές αντιφάσεις, όπως το να ζητάτε PDFACompliance μαζί με κρυπτογράφηση. Κανένα από τα δύο δεν αντικαθιστά τον εξωτερικό επικυρωτή. Απλώς εμποδίζουν αδύνατες διαμορφώσεις να φτάσουν ποτέ σε αυτόν

Οι πύλες συμμόρφωσης HotPDF στο EndDoc πιάνουν αδύνατες διαμορφώσεις πριν το veraPDF επικυρώσει PDF/A και PDF/UA και το Acrobat Preflight επικυρώσει PDF/X σε διαδρομή παράδοσης Delphi
Το HotPDF αρνείται αντιφατικές ρυθμίσεις στο EndDoc, και ανεξάρτητοι επικυρωτές αποφασίζουν την πραγματική συμμόρφωση

Μία συνήθεια αποδίδει επανειλημμένα: εκδόστε ολόκληρη τη ρύθμιση συμμόρφωσης ως ενιαία μονάδα. Η έκδοση του HotPDF, η αναθεώρηση του template, το checksum του προφίλ ICC, το build του επικυρωτή που έδωσε την έγκριση. Η συμμόρφωση παρεκκλίνει τη στιγμή που οποιοδήποτε από αυτά αλλάζει κάτω από τα υπόλοιπα, και οι πιο άσχημοι έλεγχοι είναι εκείνοι όπου κανείς δεν μπορεί να ανασυνθέσει ποιος συνδυασμός παρήγαγε ένα πενταετές αρχειακό αρχείο. Ένα ενιαίο αρχείο διαμόρφωσης ανά παρτίδα το τακτοποιεί οριστικά

Τέλος, τρέξτε τον επικυρωτή σε πραγματική έξοδο παραγωγής, ποτέ σε ένα τακτοποιημένο δείγμα χτισμένο με το χέρι. Οι αποτυχίες που δαγκώνουν προέρχονται από δεδομένα που κανείς δεν προέβλεψε: ένα λογότυπο πελάτη που φτάνει ως CMYK ενώ το intent λέει RGB, μια αλλαγή template που γλιστράει μέσα μια μη ενσωματωμένη γραμματοσειρά, μια νέα διαδρομή κώδικα που σχεδιάζει κείμενο έξω από το δέντρο ετικετών. Κρατήστε ένα γνωστά-κακό αρχείο από κάθε προηγούμενο περιστατικό ως είσοδο οπισθοδρόμησης και η πύλη συμμόρφωσης παραμένει ειλικρινής με τον καιρό. Για την πλευρά απόδοσης αυτών των αγωγών, δείτε το άρθρο μας για την έξοδο αναφορών, τις γραμματοσειρές και τις εικόνες με το HotPDF· για τη σύνδεση επικυρωτών σε ένα build, υπάρχει ένα συνοδευτικό κείμενο για την αυτοματοποίηση ελέγχων preflight PDF

Οι ιδιότητες συμμόρφωσης, τα output intent, και το API ετικετοποίησης που χρησιμοποιούνται σε αυτά τα παραδείγματα κυκλοφορούν με το HotPDF Delphi Component για Delphi και C++Builder· η σελίδα προϊόντος συνδέει την πλήρη αναφορά για κάθε κλήση που παρουσιάζεται εδώ