Bilder einer Ausstellung
Nahezu jeder Besitzer eines Computers sammelt mit der Zeit mehr oder minder viele Bilder auf seiner Festplatte an. Da kann man leicht den Überblick verlieren. Mit unserem ImageWalker-Projekt soll das nicht mehr so einfach passieren.
Die meisten Bilder, die sich so in den Tiefen von FAT und NTFS tummeln, sind GIFs, JPEGs und die allgegenwärtigen BMPs. Während Delphi mittlerweile Komponenten oder Units beinhaltet, die mit allen drei Formaten spielend ungehen können, trifft dies für den Browser, der als Anzeigemedium verwendet wird, nur bedingt zu. Zwar sind GIF und JPEG Formate, die im Internet zuhause sind, und jeder Browser kann als Viewer für diese beiden Format dienen. Die BMPs hingegen, sind in einem Format, das zwar ziemlich einfach strukturiert ist, aber seinen Lebensmittelpunkt unter Windows ansiedelt.
Also muß man sich etwas einfallen lassen, um die Bitmaps auch darstellen zu können: am Besten, man konvertiert sie in eine JPEG-Datei. Nachdem sich im Vorfeld die Farbtiefe des Bitmaps nicht abschätzen läßt, geht man mit JPEGs das geringste Risiko ein, denn die Anzahl der Bits pro Pixel ist ausreichend.
Zunächst gilt es, sich Gedanken zu machen, welche Informationen über die gefundenen Bilder wichtig sind. Dazu gehört sicherlich einmal der Dateiname, die Größe des Bildes sowohl in Bytes als auch in Pixel und auf jeden Fall das Bild selbst. Diese Informationen lassen sich schön übersichtlich in einer HTML-Tabelle unterbringen. Warum ausgerechnet HTML? Nun, wie die Prozesse über marktbeherrschendes Verhalten von Microsoft zeigen, hat so ziemlich jeder Nutzer eines PCs einen Browser auf seinem Rechner. Also, was liegt näher, als die Fähigkeiten des Browsers auf diese Weise zu nutzen. Außerdem ist es ja ganz praktisch für einen Internet-Auftritt oder ein Intranet, um einem Interessenten eine Übersicht der angebotenen Bilder zu bieten.
Thumbnail oder Original
Bei der Erzeugung der HTML-Seite soll der Anwender entscheiden können, ob er lieber die Originalbilder oder deren verkleinerte Versionen (die sogenannten Thumbnails) in die Seite aufnehmen will. Entscheidet er/sie sich für die letztere Variante, dann wäre es praktisch, ein Verzeichnis zu generieren, in dem sich die Daumennägel tummeln, anstatt sie auch noch zu den Originalen mitzupacken. Das würde nämlich bedeuten, daß – nachdem alle Dateien eines Verzeichnisses durchlaufen werden – nach den ursprünglichen Dateien auch gleich noch die Thumbnails mit bearbeitet werden.
<<<table.gif>>>
Abbildung: Von ImageWalker generierte HTML-Seite
Kasten: TGifImage
Da Delphi zwar Funktionalität mitbringt, um JPEG- und BMP-Bilder bearbeiten zu können, muß eine externe Lösung für die GIFs gefunden werden. Die geschieht in Form der TGifImage-Komponente von Anders Melander, die als Freeware verfügbar ist. Sie unterstützt Delphi 2 bis 4 und den Borland C++ Builder. Man darf sogar kommerzielle Anwendungen damit erstellen, man darf die Bibliothek nur nicht alleine vertreiben oder verändern. Im Zweifelsfall bittet der Autor darum, ihn unter anders@melander.dk zu kontaktieren, um Einzelheiten zu klären. Auf jeden Fall ist es erforderlich, daß die Lorbeeren für die GIF-Funktionalität an Anders gehen, das Info-Fenster der Applikation sollte also eine Aussage der Form “This software is based, in part, on the work of Anders Melander” oder eine gleichwertige Bemerkung enthalten.
Die Installation geht bemerkenswert leicht vonstatten: TGifImage ist eine ausführbare Datei, die mit einem Installationsprogramm ausgepackt werden kann. In Delphi muß dann nur noch die Komponente angemeldet werden, was über den Menüeintrag “Component/Install Componente...” erledigt werden kann. Anschließend muß nur noch das Package neu übersetzt werden. Nach der Installation hat sich an den vorhandenen Komponenten nicht geändert, die korrekte Verwendung von TGifImage läßt sich mit dem Einsetzen einer TImage-Komponente in ein eigenes Form und der Anwahl eines GIF-Bildes für die Eigenschaft “Picture” überprüfen.
Über die fehlende Dokumentation können die mitgelieferten HTML-Seiten mit Fragen und Antworten und das gute Dutzend Beispielprogramme durchaus hinweghelfen. Vielleicht ist bis zum Erscheinen dieses Artikels bereits eine ausführliche Dokumentation vorhanden. Die jeweils aktuelle Version von TGifImage ist unter www.melander.dk zu finden.
Ein bißchen HTML
Zäumen wir das Pferd ruhig einmal von der anderen Seite auf und betrachten zunächst die HTML-Datei, die ImageWalker erzeugt hat. Die üblichen HTML-Grundbegriffe werden an dieser Stelle, frecherweise einfach einmal vorausgesetzt. Lediglich die Anweisungen zur Generierung einer Tabelle und zum Einbinden von Bildern sollen diskutiert werden. Eine handelsübliche Tabelle sieht zum Beispiel so, oder so ähnlich aus:
<table border=”4“>
  <tr>
    <th>Dateiname</th>
    <th>Größe</th>
    <th>Bild</th>
  </tr>
  <tr>
    <td>02.jpg</td>
    <td>104092 Bytes<br>550 x 804 Pixel</td>
    <td>!!!Bild!!!</td>
  </tr>
</table>
Dabei haben wir aus Gründen der leichteren Lesbarkeit einen sog. “HTML-Beautifier“-Algorithmus in Form eines Menschen auf dieses Stück Quelltext losgelassen. Die beiden Tags “<table>” und “</table>” schließen, wie von HTML gewohnt, die Tabelle ein, die zeilenbasiert aufgebaut ist. Jede Zeile wird durch das Pärchen “<tr>” und “</tr>” (tr für table row) eingeschlossen. Die erste Zeile unterscheidet sich von jeder weiteren dadurch, daß ihre Tabellenfelder mit “<th>” und “</th>” getaggt werden, “TH” steht dabei für “table header”. Die Daten aller anderen Zeilen werden von “<td>” und “</td>” umschlossen, “TD” ist die Abkürzung für “table data”. Im dritten Feld “<td>!!!Bild!!!</td>” wird dabei von ImageWalker der Pfadname des Bildes eingefügt, so wie im folgenden Ausschnitt aus einer HTML-Seite abgebildet.
<table border="4">
<tr><th>Dateiname</th><th>Größe</th><th>Bild</th></tr>
<tr>
  <td>02.jpg</td>
  <td>104092 Bytes<br>550 x 804 Pixel</td>
  <td><a href="02.jpg"><img align="top" width="137" height="201" src="Thumb\t_02.jpg"></a></td>
</tr>
...
</table>
Dabei wird nicht nur einfach ein Dateiname eingefügt, sondern eine Reihe von Werte, die dem Browser bei der Darstellung der Tabelle helfen können. Der Anker <a href=”02.jpg”> beinhaltet den Namen des Originalbildes. Es wird angezeigt, wenn der Anwender im Browser auf den Thumbnail klickt. Alles in <img ...> dient der Darstellung des Thumbnails. Dort steht zunächst die Ausrichtung des Bildes, nämlich oben in der Tabellenzeile. Die Werte für width und height beziehen sich auf den Thumbnail und beschleunigen das Anzeigen des Thumbnails ein wenig. Und zu guter Letzt als src=”...” noch der Pfadname, wo der Browser den Thumbnail finden kann. Daß alle Werte in Hochkomma eingeschlossen sind, ist zwar nicht mehr unbedingt erforderlich, ihre Verwendung wird aber durchgängig als “gutes HTML” angesehen.
Frisch ans Werk
Nachdem die Voraussetzungen diskutiert wurden, kann es mit der Programmierung losgehen.
Beim Durchlaufen des Verzeichnisses, werden alle Dateien, die auf einer der drei Extensions BMP, GIF und JPG lauten, bearbeitet. Dabei kann der Anwender festlegen, ob kleine Vorschaubilder erzeugt werden. Während dies bei GIF und JPG recht einfach ist, müssen dafür die BMP-Dateien zunächst in JPGs umgewandelt werden, damit der Browser die Thumbnails auch darstellen kann.
<<<imgwalk.gif>>>
Abbildung: ImageWalker bei der Arbeit
Der Charme der Bibliothek TGifImage liegt darin, daß sie keine eigenständige Komponente ist, sondern die Standardkomponente TImage erweitert. So erhält man ein einziges TImage, das alle drei gewünschten Formate darstellen kann.
Var
  w, h: integer;
  ext, ThumbName: string;
  TmpPath: string;
  tmpResult: TImgInfo;
  bmp, bmp0: TBitmap;
  gif, gif0: TGifImage;
  jpg, jpg0: TJPEGImage;
begin
  ...
  if (ext = '.bmp') then begin
    if cbConvert2JPEG.Checked then begin
      ConvertBMP2JPEG (BigImageName);
      tmpResult.sLinkName := ChangeFileExt (BigImageName, '.jpg');
    end else tmpResult.sLinkName := BigImageName;
    if cbDoThumbs.Checked then begin
      // Thumbnail als JPEG erzeugen
      bmp := TBitmap.Create;
      if Need2Resize (w, h) then begin
        NewSize (w, h);
        bmp.Width := w;
        bmp.Height := h;
        bmp.Canvas.StretchDraw (Rect(0,0, bmp.Width, bmp.Height),
                                Image1.Picture.Bitmap);
      end else begin
        bmp.Width := w;
        bmp.Height := h;
        bmp.Canvas.Draw (0, 0, Image1.Picture.Bitmap);
      end;
      jpg := TJPEGImage.Create;
      jpg.Assign (bmp);
      ThumbName := ThumbDir + '\' + ChangeFileExt(ThumbPrefix + BigImageName, '.jpg');
      jpg.SaveToFile (ThumbName);
      jpg.Free;
      bmp.Free;
      tmpResult.tWidth := w;
      tmpResult.tHeight := h;
      tmpResult.sThumbName := ThumbName;
    end;
  end;
Abbildung: Auszug aus dem Quelltext zur Bearbeitung der Bitmaps
Um die optimale Größe der Thumbnails zu ermitteln, werden Breite und Höhe des Bildes solange halbiert, bis beide Werte einen vordefinierten Schwellenwert unterschreiten. Dieser Schwellenwert liegt in der Defaulteinstellung bei 300 Pixeln. Er kann aber über die Änderung des entsprechenden Eintrags in der Ini-Datei modifiziert werden. Durch die Halbierung von Breite und Höhe gleichzeitig, bleibt das Verhältnis zwischen beiden (der sogenannte Aspect Ratio) immer gleich, es treten keinerlei unerwünschte Verzerrungen des Bildes auf.
Damit unnötige Berechnungen vermieden werden, prüft ImageWalker (in der Funktion Need2Resize) vorab, ob nicht bereits die Originalgröße des Bildes in Breite und Höhe die Schwellenwerte unterschreitet. Falls nicht, erfolgt die Halbierung der Werte und damit Verkleinerung auf ein Viertel des Originalbilds. Wem diese drastische Viertelung übertrieben erscheint, dem sei eine Halbierung vorgeschlagen, indem die Werte durch “Wurzel-2” = sqr(2) dividiert werden.
// allgemeingültige Größenbestimmung für die Bitmaps
// die Abmessungen werden solange verkleinert, bis Schwellenwert unterschritten
procedure NewSize (var x,y: integer);
begin
  repeat
    // Halbierung der Werte pro Durchlauf
    // x := x div 2;
    // y := y div 2;
    // alternativ: Reduzierung um "Wurzel-2"
    x := trunc(x / sqr(2));
    y := trunc(y / sqr(2));
  until ((x <= MaxThumbSize) and (y < MaxThumbSize));
end;
Abbildung: Berechnung der Größe der Thumbnails
Da nicht alle Leser gleich ihren Compiler (soweit vorhanden) hervorholen werden, um die Software an ihre Wünsche anzupassen, sollen möglichst viele Parameter des Programmes über eine Ini-Datei einstellbar sein. Zwar sollten bereits bei Windows 95 die letzten Stündlein der INIs geschlagen haben, und alle Einstellungen ausschließlich mittels Registry ausgeführt werden, aber, wie so oft, leben die Todgesagten am längsten. Das hat sicherlich damit zu tun, daß die Hemmungen an einer Textdatei herumzuschrauben wesentlich geringer sind, als an der allmächtigen Registry, wo viel leichter etwas kaputtgehen kann. Und genau so ist es auch in diesem Falle.
[ImageWalker]
ThumbDir=thumbs
ThumbPrefix=d_
HTMLFile=sample.htm
MaxThumbSize=250
TemplatePfad=d:\beispiel\
Header=head.htm
Footer=foot.htm
Abbildung: Beispiel für eine Ini-Datei von ImageWalker
Bezeichnung	Voreinstellung	Bedeutung	
ThumbDir	Thumb	Verzeichnis, das für die Thumbnails angelegt wird	
ThumbPrefix	T_	Zeichen, die dem Bildnamen für das Thumbnail vorangestellt werden	
HTMLFile	Images.htm	Name der HTML-Datei, die mit den Bildern erzeugt wird	
MaxThumbSize	300	Maximale Größe der Thumbnails	
TemplatePfad		Pfad, in dem Header- und Footer-Datei liegen	
Header	Header.htm	Name der Datei, die vor der Tabelle in HTMLFile eingefügt wird	
Footer	Footer.htm	Name der Datei, die nach der Tabelle in HTMLFile eingefügt wird	
Abbildung: Inhalt der Ini-Datei und deren Bedeutung
Kein Abschluß?
Keine Software ist jemals wirklich fertiggestellt. Es gibt immer wieder gute Ideen, die sich umsetzen und in den bestehenden Code einbauen lassen. So ist auch dieses Projekt zu verstehen. Wenn Sie also gute Ideen haben, oder aber, was wir nicht hoffen wollen, Fehler gefunden haben, dann mailen Sie Ihre Verbesserungsvorschläge bitte an den Autor unter: agolgath@hotmail.com. Auf einige Ideen ist der Autor allerdings auch schon gekommen: so könnten die unterstützten Dateiformate erweitert werden, und zum Beispiel PNG mit aufgenommen werden. Lesen Sie auf jeden Fall die Readme-Datei, die Sie in der Zip-Datei von ImageWalker finden, dort werden alle Änderungen besprochen.
ImageWalker anwenden
Die Bedienung von ImageWalker gestaltet sich bemerkenswert einfach. Nach dem Starten öffnet sich ein Dialogfenster mit zwei Listen. In der linken Liste wird die Verzeichnisstruktur eines Laufwerks dargestellt und in der rechten Liste finden sich alle Dateien, mit denen ImageWalker etwas anfangen kann. Es sind dies Bilddateien in drei Geschmacksrichtungen: BMP, GIF und JPG. Das aktive Verzeichnis kann, wie von anderen Windows-Dialogen gewohnt problemlos gewechselt werden.
Was ImageWalker mit den Bilddateien, die es gefunden hat, machen soll, kann über die Einstellungen im rechten unteren Bereich des Dialogs festgelegt werden. So kann zum Beispiel definiert werden, ob aus den großen Bildern kleine Vorschaubilder, die sogenannten Thumbnails, erzeugt werden sollen (Häkchen bei “Thumbails erzeugen”). Im, von ImageWalker erzeugten HTML-Dokument sind dann keine Verweise auf die ursprünglichen Bilder enthalten, sondern nur Links auf die Thumbnails. Erst, wenn der Anwender im Browser dann auf das Thumbnail klickt, wird die große Version des Bildes angezeigt
Da die Browser nur bedingt etwas mit BMP-Dateien anfangen können, ist für sie eine Sonderbehandlung erforderlich. So kann der Benutzer zunächst festlegen, ob BMP-Dateien überhaupt bearbeitet werden sollen (Häkchen bei “BMP mit einschließen”). Wurde diese Option angewählt, dann werden Thumbnails für die BMPs erzeugt, allerdings im JPG-Format. Außerdem kann noch festgelegt werden, ob gefundene BMP-Dateien ins JPG-Format konvertiert werden sollen (Häkchen bei “BMP in JPEG umwandeln”). Dabei wird natürlich die originale BMP-Datei nicht gelöscht. 
Vor dem Vernichten der Bitmaps sollte allerdings berücksichtigt werden, daß es sich bei JPG in der Regel um eine verlustbehaftete Kompression handelt. Bei einer Umwandlung von BMP in JPG läßt sich eine eine Abwägung zwischen Bildqualität und der Größe der Bilddatei treffen. Erst nach einer solchen Konvertierung wird beim Klick auf das JPG-Thumbnail eines (ursprünglich nur als BMP vorliegenden Bildes) sein JPG-Zwilling angezeigt.
Nach dem Klicken auf den Button “Generieren” arbeitet sich ImageWalker durch die im rechten Listfeld angezeigten Bilder und erzeugt ein HTML-Dokument, das dann mit einem Browser betrachtet werden kann.

Änderungen
Folgende Änderungen wurden an ImageWalker seit seiner ersten Bereitstellung vorgenommen:
06.04.1999 (ag)
Bisher war es nur möglich, den Dateinamen der zu erzeugenden HTML-Datei über eine Festlegung im Ini-File zu definieren. Nunmehr gibt es erstens ein Label, in dem der Name der HTML-Datei angezeigt wird. Und zweitens kann über einen Doppelklick auf genau dieses Label ein “Sichern Als”-Dialog geöffnet und ein anderer Dateiname angegeben werden.