Ich vermute mal, dass wegen der Seltenheit des Suchwortes "IThumbnailProvider" im Laufe der Zeit noch so einige Leute über Google hierher kommen werden, von denen eine Reihe auch an der Extraktion von Vorschaubildern für ihre JPG interessiert sind.
Daher möchte ich hier erwähnen, welche Lösung ich für mich gefunden habe. Und zwar betten immer mehr Kameras in die JPG neben einem kleinen Thumbnail (APP1) auch noch ein weiteres großes Bild im Full-HD-Format ein, also 1920 x 1080 Pixel. Dies geschieht mittels MPF (Multi-Picture Format), einem Zusatz zur EXIF-Spezifikation, das im APP2 gespeichert wird. (Sogar die kleine Panasonic TZ101 tut das). Bei deutlich größeren Vorschaubildern als 120 Pixel Breite ist die Hochskalierung des eingebetteten Thumbnails keine Option, eine Vorschau größer als 1920 Pixel wird es aber wohl kaum geben. Es bietet sich also an, dieses Bild zu extrahieren und schlicht mit
StretchDraw
in der gewünschten Größe zu zeichnen.
Meine JPG haben mittlerweile locker 20 MB, während die MPF-Bilder meist zwischen 300 und 900 kB groß sind. Das Einlesen von so großen JPG und vor allem die Dekomprimierung verbrauchen enorme Zeit und Speicher. Dies bedeutet auch, dass nur relativ wenige JPG im Speicher gehalten und beim erneuten Einlesen direkt aus dem Speicher genommen werden können. Bei der MPF-Lösung werden jedoch nur die ersten 256 kB für das EXIF eingelesen (weniger als 256 kB liest Windows sowieso nicht) und dann nochmal die 300 - 900 kB für das MPF, wenn man sie selektiv aus dem Dateistream liest. Tatsächlich benötigt das Einlesen beim ersten Durchgang nur 10 msec je Datei, und ab dem zweiten nur 1 msec, und das auch bei 4.500 Dateien (16 GB Speicher).
Ich füge noch den Code bei, wie ich von TBytes zu TBitmap komme:
Delphi-Quellcode:
uses
...
JpegImage,SynGDIPlus,...
var
JpegImage:TJpegImage;
BMP:TBitmap;
TBMPF: TBytes;
Breite, Höhe: integer;
If EXIF.ExtrahiereMPF(TBMPF) then begin
JpegImage := TJpegImage.Create;
JpegImage.CreateFromBuffer(TBMPF, Length(TBMPF));
BMP := TBitmap.Create(Breite, Höhe);
BMP.PixelFormat := pf24bit;
BMP.Canvas.StretchDraw(BMP.Canvas.ClipRect,JpegImage.ToBitmap);
JpegImage.Free;
end;
ExtrahiereMPF
ist eine Methode aus meiner selbst geschriebenen EXIF-
Unit, die das MPF-Bild aus dem Filestream in einen TBytes-Puffer kopiert. Ich füge noch ein Diagramm der relevanten MPF-Struktur bei, die unglaublich kompliziert und verwirrend gestaltet wurde. Die Spezifikation findet man
hier.
.CreateFromBuffer
und
.ToBitmap
kommen aus SynGDIPlus von Synopse.
EDIT: Durch mein neues Vorgehen fällt plötzlich auf, dass keineswegs alle Bilder meiner Sony ein MPF haben, was mich total verblüfft. Eine Untersuchung zeigt, dass fast alle Bilder, die keins haben, Hochkantbilder sind. Eine Erklärung dafür könnte die sein, dass diese MPF damals eigentlich dazu eingeführt wurden, dass auf einem Fernseher ein besseres Vorschaubild gezeigt werden konnte. Da Hochkantbilder auf einem Fernseher viel kleiner dargestellt werden, wurde das bei ihnen wahrscheinlich weggelassen. Die Sony-Kameras werden in den Specs regelmäßig mit "MPF Baseline compliant" beworben. Es scheint so, als wäre eine alte Sache einfach immer weitergeführt worden. Verrückt.