Η PDF Library for Delphi δέχεται εικόνες AVIF, HEIF και JPEG XL ως είσοδο μέσω της AddModernImageFromFile και των παραλλαγών της για ροή και συμβολοσειρά, διατηρώντας άλφα, το ενσωματωμένο προφίλ ICC και κανάλια 16-bit στη διαδρομή προς το αντικείμενο εικόνας PDF. Ο εντοπισμός μορφής γίνεται με φραγμένη ανάγνωση μαγικού αριθμού, και η αποκωδικοποίηση περνά μέσα από αντικαταστάσιμο backend, οπότε τίποτα εξωτερικό δεν καλείται για ένα αρχείο που δεν είναι στην πραγματικότητα μία από αυτές τις μορφές
Αυτές οι μορφές έφτασαν στις ροές εργασίας εγγράφων μέσω κινητών τηλεφώνων. Το iOS παράγει HEIC από προεπιλογή εδώ και χρόνια, οι συσκευές Android παράγουν AVIF, και ένας τεχνικός πεδίου που φωτογραφίζει ένα κατεστραμμένο εξάρτημα στέλνει μια εικόνα που μια μηχανή αναφορών PDF χτισμένη το 2015 δεν μπορεί καν να ανοίξει. Η γενική εναλλακτική διαδρομή, αποκωδικοποίηση μέσω bitmap πλατφόρμας, αποδίδει αξιόπιστα χρώμα 8-bit και χάνει το άλφα και το προφίλ χρώματος στη διαδρομή
Τι διατηρεί η σύγχρονη διαδρομή εικόνας που χάνει μια μετατροπή bitmap;
Τρία πράγματα, και καθένα έχει μια ροή εργασίας που εξαρτάται από αυτό. Το άλφα επιβιώνει, κάτι που έχει σημασία για λογότυπα και αποκόμματα προϊόντων που συνθέτονται πάνω από περιεχόμενο σελίδας. Το προφίλ ICC επιβιώνει, κάτι που έχει σημασία για οτιδήποτε θα εκτυπωθεί ή θα αντιστοιχιστεί χρωματικά. Και τα κανάλια 16-bit επιβιώνουν, κάτι που έχει σημασία για ιατρική και επιστημονική απεικόνιση όπου η κβαντοποίηση 8-bit καταστρέφει ακριβώς τις διαβαθμίσεις για τις οποίες καταγράφηκε η εικόνα
Το πέρασμα μιας εικόνας μέσα από ένα bitmap πλατφόρμας χάνει και τα τρία σε ένα βήμα, και το κάνει σιωπηλά: το προκύπτον PDF φαίνεται περίπου σωστό, και κανείς δεν το προσέχει μέχρι ένας εκτυπωτής να ρωτήσει γιατί το εταιρικό κόκκινο είναι λάθος. Η τιμή επιλογής 8 στις σύγχρονες κλήσεις εικόνας είναι η σημαία που κρατά μαζί το άλφα, το ICC και τα κανάλια 16-bit, και είναι η προεπιλογή για εκείνες τις κλήσεις
Προσθήκη μιας εικόνας σε σελίδα
Η κλήση επιστρέφει ένα αναγνωριστικό εικόνας, το οποίο έπειτα επιλέγεται και σχεδιάζεται, ή σχεδιάζεται και απελευθερώνεται σε ένα βήμα:
uses
PDFlibrary, PDFlibModernImage;
var
Lib: TPDFlib;
ImageID: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.NewDocument;
Lib.SetPageSize('A4');
Lib.NewPage;
// Options = 8 κρατά άλφα, ICC και κανάλια 16-bit
ImageID := Lib.AddModernImageFromFile('site-photo.heic', 8);
if ImageID > 0 then
Lib.DrawImageAndRelease(ImageID, 40, 40, 515, 340)
else
Lib.DrawText(40, 40, 'image could not be decoded');
Lib.SaveToFile('inspection-report.pdf');
finally
Lib.Free;
end;
end;
Ο εντοπισμός προηγείται της αποκωδικοποίησης και είναι σκόπιμα στενός. Η βιβλιοθήκη διαβάζει μια φραγμένη κεφαλίδα, αναγνωρίζει τις μάρκες μορφής βασικού αρχείου πολυμέσων ISO που ταυτοποιούν AVIF και HEIF, και αναγνωρίζει τόσο την ακατέργαστη όσο και την υπογραφή περιέκτη του JPEG XL, έπειτα αποκαθιστά τη θέση ροής του καλούντος. Μια άγνωστη ή μεταμφιεσμένη είσοδος ποτέ δεν φτάνει στον εξωτερικό κωδικοποιητή, κάτι που εμποδίζει ένα μετονομασμένο εκτελέσιμο από το να παραδοθεί σε έναν αποκωδικοποιητή σαν να ήταν εικόνα
Πού πραγματικά συμβαίνει η αποκωδικοποίηση;
Οι σύγχρονες μορφές εικόνας είναι μεγάλοι, σύνθετοι κωδικοποιητές, και η τοποθέτηση ενός μέσα σε μια βιβλιοθήκη PDF θα ήταν παράξενη σχεδιαστική επιλογή. Το προεπιλεγμένο backend φορτώνει δυναμικά μια αναπτύξιμη μονάδα MagickWand εντός διεργασίας και την αναζητά με τεκμηριωμένη σειρά: ένα ρητό αρχείο ή κατάλογο που ρυθμίζετε, μεταβλητές περιβάλλοντος, τον κατάλογο εκτελέσιμου, και τη διαδρομή αναζήτησης συστήματος
Εφαρμογές που ήδη διανέμουν έναν αποκωδικοποιητή, ή που δεν επιτρέπεται καθόλου να φορτώσουν εξωτερική μονάδα, καταχωρούν τη δική τους επανάκληση αντ' αυτού. Το συμβόλαιο είναι μικρό: διαβάστε τη ροή εισόδου, γράψτε ένα PNG στη ροή εξόδου, τιμήστε τον ζητούμενο προσανατολισμό:
function MyDecoder(InStream, OutPNG: TStream;
ImageFormat: TPDFlibModernImageFormat;
ApplyOrientation: Boolean): Boolean;
begin
// Αποκωδικοποιήστε το InStream με τον δικό σας κωδικοποιητή και
// γράψτε byte PNG στο OutPNG
Result := DecodeWithBundledCodec(InStream, OutPNG,
ImageFormat, ApplyOrientation);
end;
begin
RegisterModernImageDecoderBackend(MyDecoder);
// ... προσθέστε εικόνες ...
ClearModernImageDecoderBackend; // επιστροφή στο προεπιλεγμένο backend
end;
Η ανάπτυξη λαμβάνει μία ευκολία και μία σκόπιμη συγκράτηση. Αν ο κατάλογος κωδικοποιητή περιέχει έναν υποκατάλογο modules\coders, η βιβλιοθήκη συμπληρώνει τις μεταβλητές περιβάλλοντος κωδικοποιητή που μια τέτοια διάταξη χρειάζεται, αλλά μόνο όταν η εφαρμογή υποδοχής δεν τις έχει ήδη ρυθμίσει. Μια εφαρμογή με τη δική της στρατηγική ανάπτυξης χρόνου εκτέλεσης την κρατά
Γιατί PNG στη μέση;
Η γεφύρωση μέσω ενός PNG στη μνήμη αντί για ακατέργαστο buffer pixel μοιάζει με επιπλέον βήμα και είναι στην πραγματικότητα το φθηνότερο σωστό. Το PNG εκφράζει ό,τι πρέπει να επιβιώσει, άλφα, τύπο χρώματος, βάθος bit και ενσωματωμένο προφίλ ICC, και η βιβλιοθήκη έχει ήδη μια ώριμη, καλά δοκιμασμένη διαδρομή από PNG σε αντικείμενο εικόνας PDF με τα σωστά φίλτρα και χώρο χρώματος. Η επαναχρησιμοποίησή της σημαίνει ότι οι σύγχρονες μορφές κληρονομούν χρόνια δουλειάς ορθότητας αντί να αποκτούν παράλληλη υλοποίηση
Η γέφυρα είναι εξ ολοκλήρου στη μνήμη, οπότε δεν δημιουργούνται προσωρινά αρχεία και δεν χρειάζεται καθαρισμός σε κατάρρευση. Μία πτυχή χρειάστηκε ρητό χειρισμό: ορισμένες μετατροπές αφαιρούν το προφίλ ICC κατά την αλλαγή μορφής. Το backend επομένως συλλαμβάνει το πηγαίο προφίλ πριν την αλλαγή μορφής, το συμπιέζει με Flate, χτίζει ένα έγκυρο τμήμα iCCP με επανυπολογισμένο CRC, και αφαιρεί οποιοδήποτε τμήμα sRGB που θα συγκρουόταν μαζί του. Σε δοκιμές, ένα αποκωδικοποιημένο AVIF κράτησε 16-bit RGBA με 16-bit άλφα, και το προφίλ που εξήχθη από το προκύπτον PDF ταίριαζε με το πηγαίο προφίλ byte προς byte σε 60.960 byte
Πρακτικές σημειώσεις πριν το ενεργοποιήσετε σε παραγωγή
Ελέγξτε τη διαθεσιμότητα κατά την εκκίνηση αντί κατά την πρώτη φωτογραφία. Η ModernImageCodecAvailable αναφέρει αν μπορεί να χρησιμοποιηθεί ένα backend, και η SetModernImageCodecLibrary δείχνει σε ρητό αρχείο ή κατάλογο όταν η ανάπτυξή σας τοποθετεί τον κωδικοποιητή κάπου μη τυπικό:
Lib.SetModernImageCodecLibrary('C:\MyApp\codecs');
if Lib.ModernImageCodecAvailable = 0 then
Log('modern image input unavailable - HEIC and AVIF will be refused');
Προσέξτε το μέγεθος αρχείου του αποτελέσματος. Μια εικόνα 16-bit RGBA με ενσωματωμένο προφίλ είναι μεγάλο αντικείμενο εικόνας PDF, και μια αναφορά με σαράντα από αυτές θα είναι μεγάλη. Όταν το έγγραφο προορίζεται για προβολή σε οθόνη αντί για εκτύπωση, η υποδειγματοληψία πριν την ενσωμάτωση είναι ο σωστός συμβιβασμός, και οι γενικοί μοχλοί μεγέθους καλύπτονται στη βελτιστοποίηση μεγέθους αρχείου PDF
Τέλος, αποφασίστε την πολιτική χρώματος σκόπιμα. Η διατήρηση του πηγαίου προφίλ είναι σωστή για αρχειακή και εκτυπωτική εργασία· η μετατροπή σε έναν χώρο σε επίπεδο εγγράφου είναι σωστή όταν ένα μεικτό σύνολο φωτογραφιών πρέπει να φαίνεται συνεπές, και η διαδρομή μετατροπής περιγράφεται στην επαναχρωματισμό ενός εγγράφου σε άλλο χώρο χρώματος. Αν χρειάζεται να επιβεβαιώσετε τι πραγματικά κατέληξε στο αρχείο, η διαδρομή επιθεώρησης στην εξαγωγή κειμένου, εικόνας και γραμματοσειράς αναφέρει τα αντικείμενα εικόνας που φέρει ένα έγγραφο
Η σύγχρονη είσοδος εικόνας, η διαχείριση χρώματος και η βελτιστοποίηση εικόνας αποτελούν μέρος της ίδιας βιβλιοθήκης για Delphi, C++Builder και Free Pascal· η πλήρης λίστα χαρακτηριστικών βρίσκεται στη σελίδα της PDF Library for Delphi