Einfaches Galerie Script ohne MySQL

Vorwort

Keine Frage, Bildgalerien auf privaten Seiten erfreuen sich großer Beliebheit. Die Angebote an Galerie Scripts reichen vom Einzeiler bis hin zu Schwergewichte wie etwa 4images oder Coppermine, die für kleinere Privatseiten aber hoffnungslos überdimensioniert sind.

Für simple Galerien hat sich im Laufe der Zeit eine Javascript Lösung durchgesetzt die wohl jeder von uns schon einmal gesehen hat. Die Rede ist von Lightbox, bzw. deren zum Teil verbesserten Versionen, Lightbox2 oder Slimbox.
Das Prinzip dieser Javascript Galerien ist ebenso einfach wie simpel: Bilder in einen Ordner laden, die Bilder ganz normal als Image im HTML einbinden, einen kleinen Zusatz in den Quelltext an dem das Script erkennt das es sich um eine Galerie handelt und das wars auch schon. Auf diese Art kann jeder, vom Laie bis zum Profi, Galerien binnen Minuten realisieren. Der einzige Nachteil ist, daß man jedes Bild einzeln und manuell einbinden muß.

Genau hier möchte ich mit diesem Tutorial ansetzen.

Um das erstellen einer Galerie, um genauer zu sein mehrere Galerien, noch einfacher zu machen, werden wir uns das Handwerkszeug dafür durch dieses Tutorial aneignen. In diesem Tutorial werden wir lernen wie man:

  • automatisiert symmetrische Thumbnails für die Vorschau erstellt
  • mit PHP eine Ordnerstruktur (die unsere Galerien darstellt) ausliest um daraus
  • automatisch die Vorschauseite mit PHP generiert, so daß Slimbox, welches wir in diesem Beispiel benutzen, uns eine navigierbare Galerie erzeugt
  • ein Downloadscript erstellt, damit man die Bilder gezielt herunterladen kann

Das hört sich im ersten Moment vielleicht kompliziert und gewaltig an aber locker bleiben, für unser Vorhaben werden wir mit weniger als 80 Zeilen PHP Code auskommen!

Voraussetzungen

Damit man diesem Tutorial folgen kann sollte man mitbringen:

  • PHP Grundlagenwissen
  • Slimbox und MooTools (Beides im Download zum Tutorial enthalten)
  • GD2 und PHP (4.3.0 oder höher) Unterstützung auf dem Server auf dem das Script laufen soll
  • Lernbereitschaft und Eigeninitiative – hier gibt es nämlich keine fix&fertig; Galerie zum produktiven Einsatz, sondern „nur“ das Wissen dazu wie man ein vollwertiges Galeriescript aufbaut!

Funktionsweise der Demo Galerie

Wie man letztendlich seine Galerie aufbauen möchte ist jedem selbst überlassen. In der Demo Galerie, die das Script aus diesem Tutorial in Aktion zeigt, habe ich folgende Funktionsweise gewählt:
Die Struktur auf dem FTP sieht so aus:

wurzelverzeichnis
|
|---- galerie.php
|---- download.php
|
|---- js
|     |
|     |---- mootools.js
|     |---- slimbox.js
|
|---- galerien
      |
      |---- Landschaften
      |     |
      |     |---- images
      |     |     |
      |     |     |---- berg.jpg
      |     |     |---- fluss.jpg
      |     |     |---- see.jpg
      |     |
      |     |---- thumbs
      |           |
      |           |---- berg.jpg
      |           |---- fluss.jpg
      |           |---- see.jpg
      |
      |---- Makros
      |     |
      |     |---- images
      |     |     |
      |     |     |---- blume.jpg
      |     |     |---- tasse.jpg
      |     |     |---- zaun.jpg
      |     |
      |     |---- thumbs
      |           |
      |           |---- blume.jpg
      |           |---- tasse.jpg
      |           |---- zaun.jpg
      |
      |---- Tierwelt
            |
            |---- images
            |     |
            |     |---- affe.jpg
            |     |---- eisbaer.jpg
            |     |---- zebra.jpg
            |
            |---- thumbs
                  |
                  |---- affe.jpg
                  |---- eisbaer.jpg
                  |---- zebra.jpg

Mit dem Thumbnail Script werden die Thumbs erstellt, die später in der Übersicht der jeweiligen Galerie angezeigt werden. Ein Klick auf ein Thumbnail öffnet das Slimbox Overlay in der die Großansicht gezeigt wird. Unterhalb der Großansicht, wo normalerweise die optionalen Informationen zum Bild stehen, befindet sich ein HTML Link, der das PHP Download Script anspricht, damit man das Bild speichern kann.

Wie man sieht ist die Funktionsweise sehr einfach gehalten. Es können beliebig viele Galerie hinzugefügt werden. Alles was dazu erfoderlich ist ist, daß man einen neuen Ordner innerhalb „galerien“ erstellt und darin dann „images“ und „thumbs“ anlegt. Das eigentliche Galeriescript wird beim nächsten Aufruf die neuen Galerien auslesen und anzeigen.

Hinweis: Sowohl für die Galerienamen (Ordnernamen) als auch für die Bilder sollte man darauf verzichten Leerzeichen, Umlaute oder sonstige Sonderzeichen zu verwenden!

So sieht das fertige Script in Aktion aus: Link zur Demo

Jetzt, da bekannt ist wie das Endprodukt aussieht, machen wir uns daran das Script zu erstellen.

Das Thumbnail Script

Das Thumbnail Script nimmt den größten Teil unseres Galerie Scripts ein. Der Grund dafür ist, daß wir nicht einfach so das Originalbild nehmen und proportional verkleinern. Macht man das, bekommt man bei der Thumbnail Vorschau einen unschönen Effekt, da auf diese Weise das Bild verkleinert wird bis entweder die Höhe oder die Breite die gewünsche Kantenlänge erreicht hat. Somit hat ein Thumbnail von einem 800×600 (Querformat) Bild andere Maße als es ein 600×800 (Hochkant) Bild hat. Hier ein Beispiel wie 2, auf 90px Kantenlänge, proportional verkleinerte Bilder aussehen:

Die Bilder wurden verkleinert bis entweder die Höhe oder die Breite 90px Kantenlänge erreicht hat. Das man so keine harmonische Übersicht hinbekommt dürfte klar sein. Deswegen wollen wir die Bilder zunächst so beschneiden, damit wir ein (temporär) quadratisches Original erzeugen und dann von diesem Bild ein Thumbnail generieren. Das Resultat sieht so aus:

Sieht doch gleich wesentlich netter aus, wenn alle Thumbnails eine einheitliche Größe haben, oder?! Schauen wir uns nun endlich den Code von thumbnail.php an…

<?php
function qThumb( $Bild, $ThumbKantenLaenge )
{
    // Masse ermitteln
    $OriginalBildInfo   = getimagesize( $Bild );
    $OriginalBildBreite = $OriginalBildInfo[0];
    $OriginalBildHoehe  = $OriginalBildInfo[1];
    $OriginalKantenLaenge = $OriginalBildBreite < $OriginalBildHoehe ? $OriginalBildBreite : $OriginalBildHoehe;
    // Temporaeres Bild vom Original erzeugen
    $TempBild = imagecreatefromjpeg( $Bild );
    // Neues Bild erstellen
    $NeuesBild = imagecreatetruecolor( $OriginalKantenLaenge, $OriginalKantenLaenge );
    // Originalbild in neues Bild einfügen
    if ($OriginalBildBreite > $OriginalBildHoehe)
    {
        imagecopy( $NeuesBild, $TempBild, 0, 0, round( $OriginalBildBreite-$OriginalKantenLaenge )/2, 0, $OriginalBildBreite, $OriginalBildHoehe );
    }
    else if ($OriginalBildBreite <= $OriginalBildHoehe )
    {
        imagecopy( $NeuesBild, $TempBild, 0, 0, 0, round( $OriginalBildHoehe-$OriginalKantenLaenge )/2, $OriginalBildBreite, $OriginalBildHoehe );
    }
 
    $Thumbnail = imagecreatetruecolor( $ThumbKantenLaenge, $ThumbKantenLaenge );
    imagecopyresampled( $Thumbnail, $NeuesBild, 0, 0, 0, 0, $ThumbKantenLaenge, $ThumbKantenLaenge, $OriginalKantenLaenge, $OriginalKantenLaenge );
    // Neues Bild ausgeben
    imagejpeg( $Thumbnail, $Bild, 80 );
    imagedestroy( $Thumbnail );
}
 
// Funktionsaufruf
foreach (glob( "*.jpg" ) as $Bild)
{
    qThumb( $Bild, 90 );
}
?>

Fangen wir hinten beim Funktionsaufruf an.

foreach (glob( "*.jpg" ) as $Bild)
{
    qThumb( $Bild, 90 );
}

Die Funktion glob() liest ein Verzeichnis aus und liefert alle gefundenen Elemente in einem Array zurück. glob() kann mit Platzhalter arbeiten, was wir hier dazu verwenden alle Dateien, symbolisiert durch den *, herauszufiltern die auf .jpg enden. Da glob() ein Array zurück liefert, können wir dieses mit einer normalen foreach-Schleife durchlaufen und jede gefundene JPG-Datei an die Funktion qThumb() übergeben. Ich habe die Funktion qThumb() genannt, da sie für quadratisches Thumbnail steht. Neben dem Bildname übergeben wir der Funktion auch die Kantenlänge in Pixel.

Springen wir nun in die Funktion qThumb() und schauen uns an was dort passiert.

$OriginalBildInfo     = getimagesize( $Bild );
$OriginalBildBreite   = $OriginalBildInfo[0];
$OriginalBildHoehe    = $OriginalBildInfo[1];
$OriginalKantenLaenge = $OriginalBildBreite < $OriginalBildHoehe ? $OriginalBildBreite : $OriginalBildHoehe;

Die Variablennamen wurden so gewählt, daß eigentlich keine großen Erklärungen nötig sein sollten. Die PHP Funktion getimagesize() liefert von einem Bild die Höhe und Breite als Pixel in einem Array. Diese Werte weisen wir eigenen Variablen zu, da diese später noch benötigt werden. In der Variable $OriginalKantenLaenge legen wir die Länge der kürzeren Kante des Bildes ab. Bei einem 800×600 Bild würden wir 600 ablegen, bei einem 768×1024 speichern wir die 768. Anhand dieser Länge errechnen wir später, wie viel Oben und Unten, bzw. Links und Rechts abgeschnitten werden muß, damit wir ein quadratisches Bild erhalten.

$TempBild  = imagecreatefromjpeg( $Bild );
$NeuesBild = imagecreatetruecolor( $OriginalKantenLaenge, $OriginalKantenLaenge );

Vom original Bild erzeugen wir eine temporäre Kopie, mit der wir im weiteren Verlauf arbeiten.
In der nächsten Zeile erzeugen wir ein neues, leeres Bild. Dieses Bild ist, wie man an der Länge/Höhe Angabe sieht, quadratisch und die Kantenlänge beträgt soviel Pixel, wie die kürzere Seite des Originals lang ist.

if ($OriginalBildBreite > $OriginalBildHoehe)
{
    imagecopy( $NeuesBild, $TempBild, 0, 0, round( $OriginalBildBreite-$OriginalKantenLaenge )/2, 0, $OriginalBildBreite, $OriginalBildHoehe );
}
else if ($OriginalBildBreite <= $OriginalBildHoehe )
{
    imagecopy( $NeuesBild, $TempBild, 0, 0, 0, round( $OriginalBildHoehe-$OriginalKantenLaenge )/2, $OriginalBildBreite, $OriginalBildHoehe );
}

Hier passiert der Trick. Wir kopieren das original Bild in das leere Bild. Dabei stellen wir zuerst fest, welche Kante die kürzere ist und führen den entsprechenden Befehl aus. Das Original wird zentriert eingefügt, so das von der längeren Kante auf beiden Seiten gleichmässig etwas übersteht und abgeschnitten wird. Mit anderen Worten: wir fügen das Bild mittig zentriert ein und schneiden alles Überschüssige ab.
Die Funktion imagecopy() ist eine Kernfunktion der Bildbearbeitung mit PHP und der GDlib, deswegen folgt hier eine kurze Erklärung der erwarteten Parameter:

  1. Ziel Image – In dieses Bild wird hinein kopiert
  2. Quell Image – Von diesem Bild wird kopiert
  3. Einfügekoordinate X – Abstand vom linken Rand (Position 0)
  4. Einfügekoordinate Y – Abstand vom oberen Rand (Position 0)
  5. Kopierkoordinate X – Ab dieser Position vom linken Rand (Position 0) wird kopiert
  6. Kopierkoordinate X – Ab dieser Position vom oberen Rand (Position 0) wird kopiert
  7. Kantenlänge X – Die Breite in Pixel die kopiert werden
  8. Kantenlänge Y – Die Höhe in Pixel die kopiert werden

Jetzt haben wir also ein quadratisches Bild aus dem Original erzeugt. Je nach dem ob das Bild Querformat oder Hochkant war, wurde Links und Rechts oder Oben und Unten etwas abgeschnitten. Jetzt müssen wir von dem quadratischen Bild nur noch ein Thumbnail erzeugen und dann ist die meiste Arbeit schon geschafft.

$Thumbnail = imagecreatetruecolor( $ThumbKantenLaenge, $ThumbKantenLaenge );
imagecopyresampled( $Thumbnail, $NeuesBild, 0, 0, 0, 0, $ThumbKantenLaenge, $ThumbKantenLaenge, $OriginalKantenLaenge, $OriginalKantenLaenge );
imagejpeg( $Thumbnail, $Bild, 80 );
imagedestroy( $Thumbnail );

Als erstes wird wieder ein leeres Bild erzeugt, diesmal aber mit den Massen des zukünftigen Thumbnails. Wieviele Pixel das genau sind teilen wir der Funktion bei deren Aufruf mit. (siehe weiter oben)
Die Funktion ImageCopyResampled() kopiert ein Bild in ein anderes und rechnet es dabei herunter. Oder vereinfacht ausgedrückt: ein Bild wird auf eine bestimmte Größe verkleinert. Diese Funktion setzt GD2 voraus. Die abwärts kompatible Variante wäre ImageCopyResize(), welche aber eine deutlich sichtbar schlechtere Qualität erzeugt!
Die letzten beiden Funktionen, imagejpeg() und imagedestroy() speichern zum einen das erzeugte Thumbnail ab und geben anschließend den belegten Arbeitsspeicher wieder frei.

Damit das Script Thumbnails erzeugen kann muß es, zusammen mit Kopien der Original Bilder, im Ordner „thumbs“ platziert werden. Nach dem erstellen der Thumbs sollte man das Script löschen, damit nicht versehentlich erneut Thumbs von den Thumbs erzeugt werden.

Jetzt da wir neben den original Bildern auch einheitliche Thumbnails haben, können wir uns um die Ausgabe kümmern. Der benötigte Code dafür ist sehr übersichtlich und leicht zu verstehen.

Die Ausgabe des Galerie Script

Damit Slimbox ihren Dienst verrichten kann müssen die benötigten Dateien in unsere index.php eingebunden werden.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de" >
<head>
<title>PHP und Slimbox Galerie</title>
 
<link rel="stylesheet" href="css/slimbox.css" type="text/css" media="screen,projection" />
<script type="text/javascript" src="js/mootools.js"></script>
<script type="text/javascript" src="js/slimbox.js"></script>
 
</head>
 
<body>
.
.
.
.
.
</body>
</html>

Slimbox benötigt neben dem eigenen Javascript noch eine CSS Datei (über die man die Ausgabe seinen Bedürfnissen anpassen kann), sowie eine JS Sammlung Namens MooTools. Details zur Anwendung und Konfiguration von Slimbox findet man auf der Anbieterseite und ist nicht direkt Gegenstand dieses Tutorials.
Da das HTML soweit vorbereitet ist, kümmern wir uns um die Ausgabe, die zwischen den Body-Tags mittels PHP erledigt wird.

$verzeichnisse = glob( "galerien/*", GLOB_ONLYDIR );
echo '<div id="nav"><ul>';
foreach ($verzeichnisse as $dir)
{
    $dirname = array_pop( explode( "/", $dir ) );
    echo '<li><a href="' .$_SERVER['PHP_SELF']. '?galerie=' .$dirname. '">' .$dirname. '</a></li>';
}
echo '</ul></div>';

Hier benutzen wir wieder glob() um die Galerienamen zu ermitteln. Da die Galerienamen durch die Ordnernamen in „galerien“ definiert werden, benutzen wir für glob() den Schalter GLOB_ONLYDIR. Wie es der Name bereits vermuten läßt, berücksichtigt glob() in dem Fall nur Ordner und ignoriert sämtliche Dateien. Wie bereits bekannt liefert diese Funktion ein Array zurück, daß wir wieder mit foreach() durchlaufen. Da wir in einem Unterodner suchen (nämlich „galerien/“) werden die gefundenen Ergebnisse mit diesem Anhängsel zurückgeliefert. Aus dem Grund trennen wir das Suchergebnis am Slash (/) und arbeiten mit dem Teil rechts davon, was im Fall des Demo Scripts die Galerien Landschaften, Makros und Tierwelt ist. Die Suchergebnisse werden als einfache ungeordnete Liste ausgegeben und auf die entsprechende Galerie verlinkt.

Klickt man auf einen Galeriename, erfolgt die Ausgabe der Thumbnails dieser Galerie. Dies erledigt dieser Code…

if (isset( $_GET['galerie'] ) )
{
    echo '<div id="preview">';
    $break = 1;
    $bilder = glob( "galerien/{$_GET['galerie']}/thumbs/*.jpg" );
    natsort( $bilder );
    foreach ($bilder as $bild)
    {
        $bild = array_pop( explode( "/", $bild ) );
        echo '<a href="galerien/' .$_GET['galerie']. '/images/' .urlencode( $bild ). '" rel="lightbox[demoscript]" title="<a href=\'download.php?get=galerien/' .$_GET['galerie']. '/images/' .urlencode( $bild ). '\'>Bild herunterladen</a>" class="thumb"><img src="galerien/' .$_GET['galerie']. '/thumbs/' .$bild. '" /></a>';
        echo ($break % 3 == 0) ? "<br />\n" : "";
        $break++;
    }
    echo '</div>';
}

In diesem Code sollte eigentlich nichts unverständliches sein. Zuerst wird geprüft ob $_GET[‚galerie‘] gesetzt ist und falls ja, werden die Dateien aus der Galerie ausgelesen und mit natsort() sortiert. Pro gefundes Thumbnail wird eine verlinkte Ausgabe gemacht und nach 3 Thumbs erzwingt man einen Zeilenumbruch.

echo ($break % 3 == 0) ? "<br />\n" : "";

Das kann man sich natürlich, je nach Thumbnail Anzahl, individuell anpassen. Wichtig für uns ist noch das title-Attribut. Normalerweise steht hier eine Information zu dem Bild, die dann im Overlay unterhalb des Bildes angezeigt werden. Wie man aber sieht ist es auch möglich HTML zu benutzen. Wir verwenden das dazu, einen Link zum Download des Bildes anzuzeigen.

Damit funktioniert unsere Galerie bereits und alles was jetzt noch fehlt ist das Download Script.

Das Download Script

Der Quelltext unserer download.php ist sehr kurz und besteht weitestgehend aus header() Anweisungen die dem Browser mitteilen das es sich um einen Download handelt.

$bildname = array_pop( explode( "/", $_GET['get'] ) );
header( "Content-Type: application/octet-stream" );
header( "Content-Disposition: attachment; filename=" .$bildname );
header( "Content-Length: " .filesize( $_GET['get'] ) );
header( "Pragma: no-cache" );
header( "Expires: 0" );
readfile( $_GET['get'] );

Die Funktionsweise ist schnell erklärt. Das Script nimmt den Dateiname aus $_GET[‚get‘] entgegen und sendet diesen als Download an den Browser.

Wie hier zu sehen ist wird der Dateiname nicht geprüft. Deswegen sollte man darauf verzichten das Listing des Download Script so auf seinem Server einzusetzen, da es eine Sicherheitslücke darstellt.
Im Zip Archiv mit den Dateien zum Tutorial ist eine verbesserte Version enthalten, die nur Downloads von JPG Dateien zuläßt.

Es steht aber jedem frei hier eine Überprüfung der Download-Anforderung einzubauen, was nicht sonderlich schwer ist.

Fazit

Wie man anhand dieses Beispiels sieht ist es ziemlich leicht sich eine kleine Galerie zu basteln. Solange man nicht eine komplizierte Galerie mit zig Funktionen benötigt, die einen Einsatz von Datenbanken erfordern, könnte dieser Lösungsansatz durchaus geeignet sein. Der Zeitaufwand ist minimal und durch das automatische erstellen der Übersicht kann man seine Galerie im handumdrehen beliebig erweitern. Das Tutorial soll nicht als fix&fertig; Lösung angesehen werden, sondern dient lediglich als Ideegeber für eigene Applikationen.

Link Übersicht

Zum Abschluß gibt es noch Links zu den verwendeten Funktionen und zum Download der Demo-Galerie.

Links zum Tutorial

Benötigte Javascript

Benutzte PHP-Funktionen

Christof Servit Administrator
Inhaber und Entwickler bei servit.biz

Ich bin spezialisiert auf die Bereiche Webentwicklung, WordPress und .net Applikationen.
Dabei spielt es keine Rolle ob Frontend oder Backend (Full-Stack). Ich unterstütze meine Kunden bei der Enwicklung, Beratung und Einrichtung in allen Bereichen.

follow me
Entwickler gesucht? Ich kann Ihnen helfen.
Ich bin spezialisiert auf die Bereiche Webentwicklung, WordPress und .net Applikationen.
Dabei spielt es keine Rolle ob Frontend oder Backend (Full-Stack).
Jetzt kontaktieren

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Scroll to Top