PDF Library for Delphi accepte les images AVIF, HEIF et JPEG XL en entrée via AddModernImageFromFile et ses variantes de flux et de chaîne, en préservant l'alpha, le profil ICC intégré et les canaux 16 bits lors de l'entrée dans l'objet image du PDF. La détection de format s'effectue sur une lecture bornée de nombre magique, et le décodage passe par un moteur remplaçable, de sorte que rien d'externe n'est invoqué pour un fichier qui n'est en réalité pas l'un de ces formats
Ces formats sont arrivés dans les flux de travail documentaires via les téléphones. iOS produit du HEIC par défaut depuis des années, les appareils Android produisent de l'AVIF, et un technicien de terrain photographiant une pièce endommagée envoie une image qu'un générateur de rapports PDF construit en 2015 ne peut pas ouvrir du tout. Le chemin de repli générique, le décodage via un bitmap de plateforme, produit invariablement une couleur 8 bits et perd l'alpha et le profil colorimétrique en chemin
Que préserve le chemin d'image moderne qu'une conversion en bitmap fait perdre ?
Trois choses, et chacune a un flux de travail qui en dépend. L'alpha survit, ce qui compte pour les logos et les découpes de produit composées par-dessus le contenu de page. Le profil ICC survit, ce qui compte pour tout ce qui sera imprimé ou calé en couleur. Et les canaux 16 bits survivent, ce qui compte pour l'imagerie médicale et scientifique où la quantification 8 bits détruit précisément les gradations pour lesquelles l'image a été capturée
Faire passer une image par un bitmap de plateforme perd les trois en une seule étape, et le fait silencieusement : le PDF résultant paraît à peu près correct, et personne ne le remarque avant qu'un imprimeur ne demande pourquoi le rouge d'entreprise est faux. La valeur d'option 8 sur les appels d'image moderne est l'indicateur qui conserve ensemble l'alpha, l'ICC et les canaux 16 bits, et c'est la valeur par défaut de ces appels
En ajouter une à une page
L'appel renvoie un identifiant d'image, qui est ensuite sélectionné et dessiné, ou dessiné et libéré en une seule étape :
uses
PDFlibrary, PDFlibModernImage;
var
Lib: TPDFlib;
ImageID: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.NewDocument;
Lib.SetPageSize('A4');
Lib.NewPage;
// Options = 8 conserve l'alpha, l'ICC et les canaux 16 bits
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;
La détection précède le décodage et est délibérément restreinte. La bibliothèque lit un en-tête borné, reconnaît les marques de format de fichier média de base ISO qui identifient AVIF et HEIF, et reconnaît à la fois les signatures brutes et conteneur du JPEG XL, puis restaure la position du flux de l'appelant. Une entrée inconnue ou déguisée n'atteint jamais le codec externe, ce qui empêche un exécutable renommé d'être remis à un décodeur comme s'il s'agissait d'une image
Où le décodage a-t-il réellement lieu ?
Les formats d'image modernes sont des codecs volumineux et complexes, et en intégrer un dans une bibliothèque PDF serait un choix de conception étrange. Le moteur par défaut charge dynamiquement un module MagickWand déployable en processus et le recherche dans un ordre documenté : un fichier ou répertoire explicite que vous définissez, des variables d'environnement, le répertoire de l'exécutable, et le chemin de recherche du système
Les applications qui livrent déjà un décodeur, ou qui ne doivent charger aucun module externe, enregistrent à la place leur propre rappel. Le contrat est réduit : lire le flux d'entrée, écrire un PNG dans le flux de sortie, respecter l'orientation demandée :
function MyDecoder(InStream, OutPNG: TStream;
ImageFormat: TPDFlibModernImageFormat;
ApplyOrientation: Boolean): Boolean;
begin
// Décodez InStream avec votre propre codec et écrivez les octets PNG dans OutPNG
Result := DecodeWithBundledCodec(InStream, OutPNG,
ImageFormat, ApplyOrientation);
end;
begin
RegisterModernImageDecoderBackend(MyDecoder);
// ... ajouter des images ...
ClearModernImageDecoderBackend; // retour au moteur par défaut
end;
Le déploiement bénéficie d'une commodité et d'une retenue délibérée. Si le répertoire de codecs contient un sous-répertoire modules\coders, la bibliothèque renseigne les variables d'environnement de codec dont une telle disposition a besoin, mais seulement lorsque l'application hôte ne les a pas déjà définies. Une application ayant sa propre stratégie de déploiement d'exécution la conserve
Pourquoi du PNG au milieu ?
Passer par un PNG en mémoire plutôt que par un tampon de pixels bruts ressemble à une étape supplémentaire et est en réalité la plus économique qui soit correcte. Le PNG exprime tout ce qui doit survivre, alpha, type de couleur, profondeur de bits et profil ICC intégré, et la bibliothèque dispose déjà d'un chemin mature et bien éprouvé du PNG vers un objet image PDF avec les bons filtres et le bon espace colorimétrique. Le réutiliser signifie que les formats modernes héritent d'années de travail de correction au lieu de recevoir une implémentation parallèle
Le pont est entièrement en mémoire, donc aucun fichier temporaire n'est créé et aucun nettoyage n'est nécessaire en cas de plantage. Une subtilité a nécessité un traitement explicite : certaines conversions abandonnent le profil ICC lors du changement de format. Le moteur capture donc le profil source avant le changement de format, le compresse avec Flate, construit un bloc iCCP valide avec un CRC recalculé, et retire tout bloc sRGB qui entrerait en conflit avec lui. Lors des tests, un AVIF décodé a conservé du RGBA 16 bits avec un alpha 16 bits, et le profil extrait du PDF résultant correspondait au profil source octet par octet, sur 60 960 octets
Remarques pratiques avant de l'activer en production
Vérifiez la disponibilité au démarrage plutôt qu'à la première photographie. ModernImageCodecAvailable indique si un moteur peut être utilisé, et SetModernImageCodecLibrary pointe vers un fichier ou répertoire explicite lorsque votre déploiement place le codec à un emplacement non standard :
Lib.SetModernImageCodecLibrary('C:\MyApp\codecs');
if Lib.ModernImageCodecAvailable = 0 then
Log('modern image input unavailable - HEIC and AVIF will be refused');
Surveillez la taille du fichier résultant. Une image RGBA 16 bits avec un profil intégré est un gros objet image PDF, et un rapport en contenant quarante sera volumineux. Lorsque le document est destiné à un affichage écran plutôt qu'à l'impression, le sous-échantillonnage avant intégration est le bon compromis, et les leviers généraux de taille sont traités dans l'optimisation de la taille des fichiers PDF
Enfin, décidez délibérément de la politique de couleur. Conserver le profil source est correct pour les travaux d'archivage et d'impression ; convertir vers un espace unique au document est correct lorsqu'un ensemble mixte de photographies doit paraître cohérent, et la méthode de conversion est décrite dans la recoloration d'un document vers un autre espace colorimétrique. Si vous devez confirmer ce qui a réellement atterri dans le fichier, le chemin d'inspection dans l'extraction de texte, d'images et de polices indique les objets image que porte un document
L'entrée d'images modernes, la gestion des couleurs et l'optimisation d'images font partie de la même bibliothèque pour Delphi, C++Builder et Free Pascal ; la liste complète des fonctionnalités se trouve sur la page PDF Library for Delphi