Thumbnails in Visual Basic

Wie könnte man eigene Thumbnails erstellen?

Um mit Bildern oder Fotos zu arbeiten, braucht man immer wieder Vorschau-Bildchen. Und die sollen bei mir möglichst groß sein. Nun habe ich mal nachgedacht, wie ein für mehrere Anwendungen gemeinsam verwendbares Thumbnail-Prinzip aussehen könnte. Es ist doch schade um die Rechenleistung, wenn man für ein Directory schon mal Miniaturansichten produziert hat, wenn man diese nicht auch in anderen Programmen mit verwenden kann.

Ein Control, das Bilder als Miniaturansicht (Thumbnails) anzeigen kann

Thumbnails als temporäre Dateien

Es ist unpraktisch, vorhandene Ordner noch zusätzlich mit Miniaturansichten zu bepacken. Also erstelle ich sie im Temp-Ordner. Dies hat den Nachteil, dass mit dem Löschen der temporären Dateien auch die Thumbnails verschwinden. Dies ist aber auch gleichzeitig ein Vorteil.

Gespeichert werden die Thumbs unter einem Pfad im temporären Ordner, der den eigentlichen Bild-Pfad auf der Festplatte oder einem Datenträger wiedergibt. Dies sieht so aus:

Public Shared Function GetThumbPath( ByVal FileName As String)
Return m_Root & FileName.Replace(":", "") & ".thmb"
End Function

m_Root wäre z.B.: IO.Path.GetTempPath & "ThumbnailCreator\"

Damit habe ich einen reproduzierbaren Pfad für alle Thumbnails.

Welches ImageFormat eignet sich am besten?

Das hängt von den Wünschen des Benutzers ab. Meine Thumbnails sollen Transparenz unterstützen, also habe ich das PNG-Format gewählt. Die Thumbnails sind maximal 400 x 400 Pixel groß, die Thumb-Dateien werden direkt als PNG gespeichert. Für meine Zwecke sind 400 Pixel optimal, diese Dateien können relativ schnell gelesen und angezeigt werden. Auf meinem Computer klappt damit sogar das "on the fly"-Zeichnen beim Bewegen der ScrollBar ohne ein Ruckeln.

Wie stellt man fest, ob Thumbnails noch aktuell sind?

Es kann passieren, dass eine Bilddatei verändert wurde, nachdem ein Thumbnail erstellt wurde. Also muss auch die Thumbnail-Datei aktualisiert werden.

Um Aktualität einer Thumb-Datei abzusichern, bringe ich beim Speichern des Thumbnails Datum/Uhrzeit des letzten Schreibzugriffs und die Datei-Größe in Bytes der Original-Bilddatei mit unter. Um festzustellen, ob die Thumbnail-Datei noch aktuell ist, vergleiche ich diese beiden Größen in der Thumb-Datei mit den im Original-Bild enthaltenen Werten.

In einem ersten Versuch habe ich ein eigenes Datei-Format erstellt. Mit einem BinaryWriter schrieb ich zuerst LastWriteTime und Length für IO.FileInfo der Original-Bilddatei. Als nächstes wurde die Thumb-PNG-Datei in diesem Stream gespeichert. So hatte ich alles in einem. Es hat auch funktioniert. Nur dauerte das Lesen der Bilddatei aus diesem zusammengesetzten Datei-Format zu langsam.

Ein Test zeigte mir, dass Image.FromFile() deutlich schneller geht, als erst einen FileStream zu erzeugen, die Position auf 16 zu stellen und dann das Bild mit Image.FromStream() zu lesen. Also brachte ich die Aktualitäts-Informationen in separaten XML-Dateien im gleichen Pfad wie die Thumbnail-Datei unter. Mit einem XML-Reader sind die hier enthaltenen Informationen auch schnell gelesen.

Das war's zu den Thumbnails.

Das Demo-Projekt

Nun ist es so weit, dieses Thumbnail-Prinzip mal auszuprobieren. Nun will ich nicht gleich den PhotoCollector neu schreiben. (zum Schluss habe ich das aber vor). Also nahm ich mir mal einen Datei-Explorer vor, mit dem ich Bild-Inhalte auf meinem Computer anschauen kann. Und zwar mit größeren Vorschau-Bildern, als Windows das kann.

Im Hintergrund arbeitet ein Thread, der immer nach neuen Thumbnails sucht, abhängig von dem, was gerade angezeigt werden soll. Dieser Thread wird beim Starten der Anwendung gestartet und endet mit dem Schließen des Programms.

Ein ThumbControl zeigt alle Dateien eines Directory als Miniaturansicht an. Dieses Control erlaubt Sortieren der angezeigten Dateien und Änderung der Anzeigegröße der Thumbnails. Auch kann man einzelne oder mehrere Items selektieren.

Zusätzlich brauchte ich noch ein Control, mit dem ich eine Directory-Struktur auf der Festplatte im TreeView-Style durchsehen kann. Dieses Control heißt hier FolderTreeView und liefert mir ein Event für Änderung und den gerade ausgewählten Pfad.

Das Resultat stellt mich ganz zufrieden. Allerdings, mein Computer ist schnell. Damit klappt auch ruckelfreies Scrollen bei gleichzeitig dynamischem Erstellen und wieder Löschen der Thumbnail-Bitmaps, die beim Scrollen sichtbar oder unsichtbar werden. Meinen Computer meldete bei dieser Arbeitsweise allerdings immer wieder durch Anschalten des Lüfters, dass er gerade ziemlich an seinen Grenzen ist. Also hab ich auf das Disposing der Thumbnail-Bitmaps beim Scrollen verzichtet. Offenbar kann .NET ganz gut auch eine ganze Menge an Bitmap-Dateien temporär zwischenspeichern.

Nun, probiert das Beispiel bitte mal aus und teilt mir mit, ob's funktioniert. Auf schnelleren Computern sollte es unbedingt funktionieren. Wenn ja, hätten wir ein von mehreren Programmen gleichzeitig verwendbares Prinzip, mit dem größere Thumbnails erstellt und genutzt werden können.

Grüße,

Thomas Bergner