Teknisk artikel

Indlejr AVIF-, HEIF- og JPEG XL-billeder i PDF fra Delphi

PDF Library for Delphi accepterer AVIF-, HEIF- og JPEG XL-billeder som input via AddModernImageFromFile og dens stream- og strengvarianter, og bevarer alfa, den indlejrede ICC-profil og 16-bit-kanaler på vejen ind i PDF-billedobjektet. Formatdetektion sker på en afgrænset magisk-tal-læsning, og afkodning kører gennem en udskiftelig backend, så intet eksternt kaldes for en fil, der faktisk ikke er ét af disse formater

Disse formater ankom i dokumentarbejdsgange via telefoner. iOS har produceret HEIC som standard i årevis, Android-enheder producerer AVIF, og en felttekniker, der fotograferer en beskadiget del, sender et billede, som en PDF-rapportgenerator bygget i 2015 slet ikke kan åbne. Den generiske fallback-sti, afkodning via et platformsbitmap, giver pålideligt 8-bit farve og mister alfa og farveprofilen undervejs

Hvad bevarer den moderne billedsti, som en bitmap-konvertering mister?

Tre ting, og hver har en arbejdsgang, der afhænger af den. Alfa overlever, hvilket betyder noget for logoer og produktudklip komponeret over sideindhold. ICC-profilen overlever, hvilket betyder noget for alt, der skal trykkes eller farvematches. Og 16-bit-kanaler overlever, hvilket betyder noget for medicinsk og videnskabelig billeddannelse, hvor 8-bit-kvantisering ødelægger netop de nuancer, billedet blev fanget for

At sende et billede gennem et platformsbitmap mister alle tre i ét trin, og det gør det stiltiende: den resulterende PDF ser omtrent rigtig ud, og ingen bemærker det, før en trykker spørger, hvorfor den corporate røde er forkert. Optionsværdi 8 på de moderne billedkald er flaget, der holder alfa, ICC og 16-bit-kanaler sammen, og det er standarden for disse kald

At tilføje ét til en side

Kaldet returnerer en billedidentifikator, som derefter vælges og tegnes, eller tegnes og frigives i ét trin:

uses
  PDFlibrary, PDFlibModernImage;

var
  Lib: TPDFlib;
  ImageID: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.NewDocument;
    Lib.SetPageSize('A4');
    Lib.NewPage;

    // Options = 8 holder alfa, ICC og 16-bit-kanaler
    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;

Detektion går forud for afkodning og er bevidst snæver. Biblioteket læser et afgrænset header, genkender de ISO base media file format-mærker, der identificerer AVIF og HEIF, og genkender både de rå og container-signaturer for JPEG XL, og genopretter derefter den kaldendes streamposition. Et ukendt eller camoufleret input når aldrig den eksterne codec, hvilket forhindrer en omdøbt eksekverbar fil i at blive overdraget til en afkoder, som var den et billede

Hvor sker afkodningen egentlig?

Moderne billedformater er store, komplekse codecs, og at putte en inde i et PDF-bibliotek ville være et mærkeligt designvalg. Standard-backenden indlæser dynamisk et udrulbart MagickWand-modul in-process og leder efter det i en dokumenteret rækkefølge: en eksplicit fil eller mappe, du sætter, miljøvariabler, den eksekverbare mappe og systemets søgesti

Applikationer, der allerede leverer en afkoder, eller som slet ikke må indlæse et eksternt modul, registrerer i stedet deres eget callback. Kontrakten er lille: læs inputstrømmen, skriv en PNG til outputstrømmen, respektér den anmodede orientering:

function MyDecoder(InStream, OutPNG: TStream;
  ImageFormat: TPDFlibModernImageFormat;
  ApplyOrientation: Boolean): Boolean;
begin
  // Afkod InStream med din egen codec, og skriv PNG-bytes til OutPNG
  Result := DecodeWithBundledCodec(InStream, OutPNG,
    ImageFormat, ApplyOrientation);
end;

begin
  RegisterModernImageDecoderBackend(MyDecoder);
  // ... tilføj billeder ...
  ClearModernImageDecoderBackend;    // tilbage til standard-backenden
end;

Udrulning får én bekvemmelighed og én bevidst tilbageholdenhed. Hvis codec-mappen indeholder en undermappe modules\coders, udfylder biblioteket de codec-miljøvariabler, et sådant layout kræver, men kun når værtsapplikationen ikke allerede har sat dem. En applikation med sin egen runtime-udrulningsstrategi beholder den

Hvorfor PNG i midten?

At bygge bro via en PNG i hukommelsen frem for en rå pixelbuffer ligner et ekstra trin og er faktisk det billigste korrekte ét. PNG udtrykker alt, der skal overleve, alfa, farvetype, bitdybde og en indlejret ICC-profil, og biblioteket har allerede en moden, veltestet sti fra PNG ind i et PDF-billedobjekt med de rigtige filtre og farverum. At genbruge den betyder, at moderne formater arver års korrekthedsarbejde i stedet for at få en parallel implementering

Broen er udelukkende i hukommelsen, så ingen midlertidige filer oprettes, og ingen oprydning er nødvendig ved et nedbrud. Ét vrid krævede eksplicit håndtering: nogle konverteringer dropper ICC-profilen ved formatskift. Backenden fanger derfor kildeprofilen før formatskiftet, komprimerer den med Flate, bygger en gyldig iCCP-chunk med en genberegnet CRC og fjerner enhver sRGB-chunk, der ville kollidere med den. I test beholdt en afkodet AVIF 16-bit RGBA med 16-bit alfa, og profilen udtrukket fra den resulterende PDF matchede kildeprofilen byte for byte ved 60.960 bytes

Praktiske noter, før du aktiverer det i produktion

Tjek tilgængelighed ved opstart frem for ved det første fotografi. ModernImageCodecAvailable rapporterer, om en backend kan bruges, og SetModernImageCodecLibrary peger på en eksplicit fil eller mappe, når din udrulning placerer codec'en et ikke-standardsted:

Lib.SetModernImageCodecLibrary('C:\MyApp\codecs');
if Lib.ModernImageCodecAvailable = 0 then
  Log('modern image input unavailable - HEIC and AVIF will be refused');

Hold øje med filstørrelsen af resultatet. Et 16-bit RGBA-billede med en indlejret profil er et stort PDF-billedobjekt, og en rapport med fyrre af dem bliver stor. Når dokumentet er bestemt til skærmvisning frem for tryk, er nedskalering før indlejring det rigtige valg, og de generelle størrelseshåndtag er dækket i PDF-filstørrelsesoptimering

Beslut endelig farvepolitik bevidst. At beholde kildeprofilen er korrekt til arkiv- og trykarbejde; at konvertere til et dokumentbredt farverum er korrekt, når et blandet sæt fotografier skal se ensartet ud, og konverteringsruten er beskrevet i omfarvning af et dokument til et andet farverum. Hvis du har brug for at bekræfte, hvad der rent faktisk endte i filen, rapporterer inspektionsstien i udtræk af tekst, billede og skrifttype de billedobjekter, et dokument bærer

Moderne billedinput, farvestyring og billedoptimering er en del af det samme bibliotek til Delphi, C++Builder og Free Pascal; den komplette funktionsliste findes på siden PDF Library til Delphi