PDF Library for Delphi akzeptiert AVIF-, HEIF- und JPEG-XL-Bilder als Eingabe über AddModernImageFromFile sowie dessen Stream- und String-Varianten und erhält dabei Alphakanal, das eingebettete ICC-Profil und 16-Bit-Kanäle auf dem Weg in das PDF-Bildobjekt. Die Formaterkennung erfolgt anhand eines begrenzten Magic-Number-Lesevorgangs, und das Dekodieren läuft über ein austauschbares Backend, sodass für eine Datei, die tatsächlich keinem dieser Formate entspricht, nichts Externes aufgerufen wird
Diese Formate fanden über Smartphones Einzug in Dokument-Workflows. iOS erzeugt seit Jahren standardmäßig HEIC, Android-Geräte erzeugen AVIF, und ein Außendiensttechniker, der ein beschädigtes Teil fotografiert, schickt ein Bild, das ein 2015 gebauter PDF-Berichtsgenerator überhaupt nicht öffnen kann. Der generische Fallback-Pfad, das Dekodieren über eine Plattform-Bitmap, liefert zuverlässig 8-Bit-Farbe und verliert dabei Alphakanal und Farbprofil
Was erhält der moderne Bildpfad, das eine Bitmap-Konvertierung verliert?
Drei Dinge, und jedes hat einen Workflow, der davon abhängt. Der Alphakanal bleibt erhalten, was für Logos und über Seiteninhalt gelegte Produktfreisteller wichtig ist. Das ICC-Profil bleibt erhalten, was für alles wichtig ist, das gedruckt oder farblich abgeglichen wird. Und 16-Bit-Kanäle bleiben erhalten, was für medizinische und wissenschaftliche Bildgebung wichtig ist, wo 8-Bit-Quantisierung genau die Abstufungen zerstört, für die das Bild aufgenommen wurde
Ein Bild durch eine Plattform-Bitmap zu schicken verliert alle drei in einem Schritt, und das geschieht lautlos: Das entstehende PDF sieht ungefähr richtig aus, und niemand bemerkt es, bis eine Druckerei fragt, warum das Firmenrot falsch ist. Optionswert 8 bei den modernen Bildaufrufen ist das Flag, das Alphakanal, ICC-Profil und 16-Bit-Kanäle zusammen erhält, und es ist der Standard für diese Aufrufe
Ein Bild einer Seite hinzufügen
Der Aufruf gibt eine Bildkennung zurück, die dann ausgewählt und gezeichnet oder in einem Schritt gezeichnet und freigegeben wird:
uses
PDFlibrary, PDFlibModernImage;
var
Lib: TPDFlib;
ImageID: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.NewDocument;
Lib.SetPageSize('A4');
Lib.NewPage;
// Options = 8 erhält Alphakanal, ICC-Profil und 16-Bit-Kanäle
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;
Die Erkennung erfolgt vor dem Dekodieren und ist bewusst eng gefasst. Die Bibliothek liest einen begrenzten Header, erkennt die ISO-Base-Media-File-Format-Kennungen, die AVIF und HEIF identifizieren, sowie sowohl die rohe als auch die Container-Signatur von JPEG XL, und stellt anschließend die Stream-Position des Aufrufers wieder her. Eine unbekannte oder getarnte Eingabe erreicht niemals den externen Codec, was verhindert, dass eine umbenannte ausführbare Datei einem Decoder übergeben wird, als wäre sie ein Bild
Wo findet das Dekodieren tatsächlich statt?
Moderne Bildformate sind große, komplexe Codecs, und einen davon in eine PDF-Bibliothek zu packen wäre eine seltsame Designentscheidung. Das Standard-Backend lädt dynamisch ein bereitstellbares MagickWand-Modul im selben Prozess und sucht danach in einer dokumentierten Reihenfolge: ein explizit gesetzter Datei- oder Verzeichnispfad, Umgebungsvariablen, das Verzeichnis der ausführbaren Datei und der System-Suchpfad
Anwendungen, die bereits einen Decoder mitbringen oder überhaupt kein externes Modul laden dürfen, registrieren stattdessen ihren eigenen Callback. Der Vertrag ist klein: den Eingabestream lesen, ein PNG in den Ausgabestream schreiben, die angeforderte Orientierung beachten:
function MyDecoder(InStream, OutPNG: TStream;
ImageFormat: TPDFlibModernImageFormat;
ApplyOrientation: Boolean): Boolean;
begin
// InStream mit dem eigenen Codec dekodieren und PNG-Bytes in OutPNG schreiben
Result := DecodeWithBundledCodec(InStream, OutPNG,
ImageFormat, ApplyOrientation);
end;
begin
RegisterModernImageDecoderBackend(MyDecoder);
// ... Bilder hinzufügen ...
ClearModernImageDecoderBackend; // zurück zum Standard-Backend
end;
Die Bereitstellung bringt eine Annehmlichkeit und eine bewusste Zurückhaltung mit sich. Enthält das Codec-Verzeichnis ein Unterverzeichnis modules\coders, füllt die Bibliothek die Codec-Umgebungsvariablen aus, die ein solches Layout benötigt, jedoch nur, wenn die Host-Anwendung sie nicht bereits gesetzt hat. Eine Anwendung mit eigener Runtime-Bereitstellungsstrategie behält diese bei
Warum PNG als Zwischenschritt?
Die Überbrückung über ein PNG im Arbeitsspeicher statt über einen rohen Pixelpuffer wirkt wie ein zusätzlicher Schritt und ist tatsächlich der günstigste korrekte. PNG drückt alles aus, was erhalten bleiben muss – Alphakanal, Farbtyp, Bittiefe und ein eingebettetes ICC-Profil –, und die Bibliothek besitzt bereits einen ausgereiften, gut getesteten Pfad von PNG in ein PDF-Bildobjekt mit den richtigen Filtern und dem richtigen Farbraum. Ihn wiederzuverwenden bedeutet, dass moderne Formate von Jahren an Korrektheitsarbeit profitieren, statt eine parallele Implementierung zu bekommen
Die Brücke liegt vollständig im Arbeitsspeicher, daher werden keine temporären Dateien erstellt und es ist keine Aufräumarbeit bei einem Absturz nötig. Eine Besonderheit brauchte explizite Behandlung: Manche Konvertierungen verwerfen das ICC-Profil beim Formatwechsel. Das Backend erfasst daher das Quellprofil vor dem Formatwechsel, komprimiert es mit Flate, baut einen gültigen iCCP-Chunk mit neu berechneter CRC auf und entfernt einen etwaigen sRGB-Chunk, der damit in Konflikt stünde. Im Test behielt ein dekodiertes AVIF 16-Bit-RGBA mit 16-Bit-Alphakanal, und das aus dem entstandenen PDF extrahierte Profil stimmte mit dem Quellprofil byteidentisch bei 60.960 Bytes überein
Praktische Hinweise vor der Aktivierung im Produktivbetrieb
Verfügbarkeit beim Start prüfen, nicht erst beim ersten Foto. ModernImageCodecAvailable meldet, ob ein Backend genutzt werden kann, und SetModernImageCodecLibrary verweist auf eine explizite Datei oder ein Verzeichnis, wenn das eigene Deployment den Codec an ungewöhnlicher Stelle ablegt:
Lib.SetModernImageCodecLibrary('C:\MyApp\codecs');
if Lib.ModernImageCodecAvailable = 0 then
Log('modern image input unavailable - HEIC and AVIF will be refused');
Die Dateigröße des Ergebnisses im Blick behalten. Ein 16-Bit-RGBA-Bild mit eingebettetem Profil ist ein großes PDF-Bildobjekt, und ein Bericht mit vierzig davon wird groß. Ist das Dokument für die Bildschirmanzeige statt für den Druck bestimmt, ist Downsampling vor dem Einbetten der richtige Kompromiss, und die allgemeinen Stellschrauben für die Größe werden in PDF-Dateigrößenoptimierung behandelt
Schließlich sollte die Farbpolitik bewusst festgelegt werden. Das Quellprofil zu behalten ist für Archivierung und Druckarbeit korrekt; die Konvertierung in einen dokumentweiten Farbraum ist korrekt, wenn eine gemischte Menge von Fotografien einheitlich aussehen muss, und der Konvertierungsweg wird in Umfärben eines Dokuments in einen anderen Farbraum beschrieben. Muss bestätigt werden, was tatsächlich in der Datei gelandet ist, meldet der Inspektionspfad in Text-, Bild- und Schriftextraktion die Bildobjekte, die ein Dokument trägt
Moderne Bildeingabe, Farbmanagement und Bildoptimierung sind Teil derselben Bibliothek für Delphi, C++Builder und Free Pascal; die vollständige Funktionsliste findet sich auf der PDF-Library-für-Delphi-Seite