Teknisk artikel

Bädda in AVIF-, HEIF- och JPEG XL-bilder i PDF från Delphi

PDF Library for Delphi accepterar AVIF-, HEIF- och JPEG XL-bilder som indata via AddModernImageFromFile och dess ström- och strängvarianter, och bevarar alfa, den inbäddade ICC-profilen och 16-bitars kanaler på väg in i PDF-bildobjektet. Formatdetektering sker via en begränsad läsning av magiska tal, och avkodning körs genom en utbytbar backend, så inget externt anropas för en fil som faktiskt inte är något av dessa format

Dessa format kom in i dokumentarbetsflöden via telefoner. iOS har producerat HEIC som standard i flera år, Android-enheter producerar AVIF, och en fälttekniker som fotograferar en skadad del skickar en bild som en PDF-rapportgenerator byggd 2015 inte kan öppna alls. Den generiska reservvägen, avkodning via en plattformsbitmapp, ger tillförlitligt 8-bitars färg och förlorar alfa och färgprofilen längs vägen

Vad bevarar den moderna bildvägen som en bitmappskonvertering förlorar?

Tre saker, och var och en har ett arbetsflöde som beror på den. Alfa överlever, vilket spelar roll för logotyper och produkturklipp komponerade ovanpå sidinnehåll. ICC-profilen överlever, vilket spelar roll för allt som ska tryckas eller färgmatchas. Och 16-bitars kanaler överlever, vilket spelar roll för medicinsk och vetenskaplig bildbehandling där 8-bitars kvantisering förstör just de gradationer bilden fångades för

Att föra en bild genom en plattformsbitmapp förlorar alla tre i ett steg, och det gör det tyst: den resulterande PDF:en ser ungefär rätt ut, och ingen märker det förrän en tryckare frågar varför det företagsröda är fel. Alternativvärde 8 på de moderna bildanropen är flaggan som håller alfa, ICC och 16-bitars kanaler tillsammans, och det är standardvärdet för dessa anrop

Att lägga till en på en sida

Anropet returnerar en bildidentifierare, som sedan väljs och ritas, eller ritas och frisläpps i ett steg:

uses
  PDFlibrary, PDFlibModernImage;

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

    // Options = 8 behåller alfa, ICC och 16-bitars 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;

Detektering föregår avkodning och är medvetet snäv. Biblioteket läser ett begränsat huvud, känner igen de ISO-baserade mediefilformatsmärken som identifierar AVIF och HEIF, och känner igen både de råa och behållarsignaturerna för JPEG XL, och återställer sedan anroparens strömposition. En okänd eller maskerad indata når aldrig den externa kodeken, vilket hindrar en omdöpt körbar fil från att lämnas till en avkodare som om den vore en bild

Var sker avkodningen egentligen?

Moderna bildformat är stora, komplexa kodekar, och att lägga en inuti ett PDF-bibliotek vore ett märkligt designval. Standardbackenden laddar dynamiskt en driftsättningsbar MagickWand-modul i processen och letar efter den i en dokumenterad ordning: en explicit fil eller katalog du anger, miljövariabler, den körbara katalogen och systemets sökväg

Applikationer som redan levererar en avkodare, eller som inte alls får ladda en extern modul, registrerar istället sin egen callback. Kontraktet är litet: läs indataströmmen, skriv en PNG till utdataströmmen, respektera den begärda orienteringen:

function MyDecoder(InStream, OutPNG: TStream;
  ImageFormat: TPDFlibModernImageFormat;
  ApplyOrientation: Boolean): Boolean;
begin
  // Avkoda InStream med din egen kodek och skriv PNG-byte till OutPNG
  Result := DecodeWithBundledCodec(InStream, OutPNG,
    ImageFormat, ApplyOrientation);
end;

begin
  RegisterModernImageDecoderBackend(MyDecoder);
  // ... lägg till bilder ...
  ClearModernImageDecoderBackend;    // tillbaka till standardbackend
end;

Driftsättning får en bekvämlighet och en medveten återhållsamhet. Om kodekkatalogen innehåller en underkatalog modules\coders fyller biblioteket i de kodekmiljövariabler en sådan layout behöver, men bara när värdapplikationen inte redan har satt dem. En applikation med sin egen körtidsdriftsättningsstrategi behåller den

Varför PNG i mitten?

Att bygga en bro via en PNG i minnet snarare än en rå pixelbuffert ser ut som ett extra steg och är faktiskt det billigaste korrekta. PNG uttrycker allt som måste överleva, alfa, färgtyp, bitdjup och en inbäddad ICC-profil, och biblioteket har redan en mogen, väl testad väg från PNG till ett PDF-bildobjekt med rätt filter och färgrymd. Att återanvända den betyder att moderna format ärver år av korrekthetsarbete istället för att få en parallell implementation

Bron ligger helt i minnet, så inga temporära filer skapas och ingen upprensning behövs vid en krasch. En detalj krävde explicit hantering: vissa konverteringar tappar ICC-profilen vid formatbyte. Backenden fångar därför källprofilen innan formatbytet, komprimerar den med Flate, bygger en giltig iCCP-chunk med en omberäknad CRC, och tar bort varje sRGB-chunk som skulle stå i konflikt med den. Vid testning behöll en avkodad AVIF 16-bitars RGBA med 16-bitars alfa, och profilen som extraherades från den resulterande PDF:en matchade källprofilen byte för byte vid 60 960 byte

Praktiska noteringar innan du aktiverar det i produktion

Kontrollera tillgänglighet vid uppstart snarare än vid första fotografiet. ModernImageCodecAvailable rapporterar om en backend kan användas, och SetModernImageCodecLibrary pekar mot en explicit fil eller katalog när din driftsättning placerar kodeken någon icke-standardplats:

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

Håll koll på resultatets filstorlek. En 16-bitars RGBA-bild med en inbäddad profil är ett stort PDF-bildobjekt, och en rapport med fyrtio av dem blir stor. När dokumentet är avsett för skärmvisning snarare än tryck är nedsampling före inbäddning rätt avvägning, och de allmänna storleksspakarna täcks i PDF-filstorleksoptimering

Bestäm slutligen färgpolicy medvetet. Att behålla källprofilen är korrekt för arkiv- och tryckarbete; att konvertera till en dokumentomfattande rymd är korrekt när en blandad uppsättning fotografier måste se enhetlig ut, och konverteringsvägen beskrivs i omfärgning av ett dokument till en annan färgrymd. Om du behöver bekräfta vad som faktiskt hamnade i filen rapporterar inspektionsvägen i extraktion av text, bild och typsnitt de bildobjekt ett dokument bär

Modern bildindata, färghantering och bildoptimering är delar av samma bibliotek för Delphi, C++Builder och Free Pascal; den fullständiga funktionslistan finns på sidan för PDF Library for Delphi