Gdlib

Aus THM-Wiki
Wechseln zu: Navigation, Suche

Einleitung

Was ist die gdLib

Gdlogobig.png

Die gd Library ist eine Open Source Bibliothek mit Funktionen für das dynamische Erstellen von Grafiken. Die Bibliothek wurde in C geschrieben und kann JPEG, PNG und GIF Bilder erzeugen und manipulieren. Sogenannte "Wrapper" gibt es für verschiedene Sprachen, unter anderem Perl und PHP, wobei ich nur auf die Nutzung im Rahmen von PHP Skripten eingehen werde.

Einbinden

Seit PHP Version 4.3.0 wird die gdLib "gebundled" mitgeliefert. Falls sie noch nicht aktiviert wurde, kann man dies durch erneutes Konfigurieren machen.

configure PHP --with-gd[=DIR] (DIR steht für das Installations-Verzeichnis der gdLib).

Eine zweite Möglichkeit wäre, die gdLib von der Entwickler-Seite herunterzuladen und manuell einzubinden. Es ist jedoch empfehlenswert, eine aktuelle PHP Version zu nutzen, worin die gdLib integriert ist. Man hat den Vorteil, dass der Code wesentlich stabiler läuft und auch zuverlässiger/regelmäßig gewartet wird.

Windowsnutzer können die gdLib als Extension einbinden. Hierzu benötigt man die GD2-DLL (php_gd2.dll). Das Einbinden findet in der php.ini-Datei statt.

z.B. extension_dir = "c:\php\ext"

Hier sollte darauf geachtet werden, dass der Extension-Pfad korrekt gesetzt ist und der Verzeichnisname nicht länger als 8 Zeichen ist - dies kann zu Konflikten mit der PHP-Einbindung führen. Die eigentliche DLL wird mit folgender Zeile eingebunden:

extension=php_gd.dll

Getting Started

Man unterscheidet im Wesentlichen zwei Arten der Benutzung von der gdLib. Man kann sie dazu verwenden Grafiken einmalig zu erzeugen und im Browser darzustellen, oder um die erzeugten Grafiken direkt auf dem Server zu speichern. Dementsprechend sollte man auch auf den Aufbau des PHP-Skripts achten.

Wenn man nur die Grafik ausgeben möchte anstatt diese auf dem Server zu speichern, ist darauf zu achten, dass man keine Ausgabe im PHP-Skript durchführt und der Seitenheader entsprechend des Grafikformats gesetzt wird. Beim Speichern hingegen kann man im Skript und auch zwischen einzelnen Grafikfunktionen z.B. eine echo-Ausgabe durchführen.

Beispiel für die einmalige Erzeugung und Darstellung der Grafik im Browser:

<?php
  # gd01.php

  # festlegen, was fuer ein Bild dargestellt werden soll
  header("Content-type: image/png");
 
  # Bild erzeugen...
  $img = imagecreatetruecolor(200, 100);
  
  # Bild ausgeben...
  imagepng($img, "bild.png");

  # freigeben des allokierten Speichers...
  imagedestroy($img);
?> 

Und nun das entsprechende Beispiel für das Abspeichern der Grafik:

<?php
  # gd02.php

  echo 'Bild erzeugen...<br />';
  $img = imagecreatetruecolor(200, 100);
  
  echo 'Bild speichern...<br />';
  imagepng($img, "bild.png");

  echo 'freigeben des allokierten Speichers... <br />';
  imagedestroy($img);

  echo '<br /> <img src="bild.png" title="erzeugtes Bild" />';
?> 

Wie man im zweiten Quelltext sehen kann, wird zwischen den Grafikbefehlen ein echo ausgeführt. Dieses Skript greift lediglich zum Ende hin auf das Dateisystem zu, um die Grafik abzuspeichern. Wobei beim ersten Quelltext der Header für die Browser-Ausgabe auf ein PNG-Bild gesetzt wird. Somit weiß der Browser, dass die Ausgabe des Skripts ein Bild repräsentieren soll. Beim Fehlschlagen eines Befehls innerhalb des Skripts wird die Fehlermeldung ausgegeben und der Browser interpretiert diesen Text nicht als Grafik.

Basis-Funktionen

Die wichtigsten Funktionen im Überblick

Bild erzeugen

Bilder kann man mit der gdLib auf verschiedene Arten erzeugen. Entweder erstellt man ein neues Bild mit der Funktion imagecreatetruecolor(); (siehe gd01.php) oder man lädt ein Bild aus dem Dateisystem in eine Variable (vergleichbar mit dem Device-Context (DC) in der WinAPI-Programmierung).

Beim Erzeugen eines neuen Bildes ist darauf zu achten, dass der Befehl imagecreatetruecolor(); nur ab der GD2 Version verfügbar ist und ein leeres Bild mit schwarzem Hintergrund erzeugt. Falls man noch nicht über die GD2 verfügt (Version < 2.0.1), kann man ein Bild mit imagecreate(); erzeugen.

Beim Laden der Datei muss darauf geachtet werden, welches Dateiformat das zu ladende Bild hat. Derzeit werden PNG-, JPG- und GIF-Bilder unterstützt und sind je nachdem mit folgenden Befehlen zu laden: imagecreatefromjpeg();, imagecreatefrompng();, imagecreatefromgif();. Folgendes Skript lädt ein PNG-Bild in die Ressource und gibt es im Browser aus.

<?php
  # gd03.php

  # festlegen, was fuer ein Bild dargestellt werden soll
  header("Content-type: image/png");

  # Bilddatei wird in eine Ressource $img geladen 
  $img = imagecreatefrompng("gdlogobig.png");
  
  # Bild ausgeben
  imagepng($img);

  # freigeben des allokierten Speichers...
  imagedestroy($img);
?> 

Bild-Informationen

Die wohl beiden wichtigsten Informationen in einem Bild sind die Breite und die Höhe. Hat man eine Bildressource vorliegen, kann man mit den Befehlen imagesx(); und imagesy(); die Breite und Höhe ermitteln.

<?php
  # gd04.php

  # Bilddatei wird in eine Ressource $img geladen 
  $img = imagecreatefrompng("gdlogobig.png");
  
  # Bild-Informationen ausgeben
  echo 'Breite: ' . imagesx($img) . 'px <br />';
  echo 'Höhe: ' . imagesy($img) . 'px';

  # freigeben des allokierten Speichers...
  imagedestroy($img);
?> 

Mit der Funktion getimagesize(); kann man diese Angaben ebenfalls bestimmen. Hierbei muss der Dateiname übergeben werden und es wird ein Array zurückgegeben, wo im Feld [0] die Breite und im Feld [1] die Höhe des Bildes enthalten ist. Bei beiden Arten handelt es sich jeweils um Pixelangaben.

Bilder kopieren und skalieren

Ein großer Vorteil beim Arbeiten mit den Bildressourcen ist, dass es egal ist, welches der 3 Formate das Quellbild bzw. das Zielbild hat. Fangen wir mit einem einfachen Beispiel an. Das folgende Skript lädt das gdLib-Logo aus einer Datei und gibt es in halber Größe im Browser aus.

<?php
  # gd05.php

  # festlegen, was fuer ein Bild dargestellt werden soll
  header("Content-type: image/png");

  # Bilddatei wird in eine Ressource $img geladen 
  $img = imagecreatefrompng("gdlogobig.png");

  # Bildgröße ermitteln
  $ow = imagesx($img);
  $oh = imagesy($img);
  
  # Neue (halbe) Bildgröße berechnen
  $nw = round($ow / 2);
  $nh = round($oh / 2);

  # Neues Bild erzeugen
  $img2 = imagecreatetruecolor($nw, $nh);
  
  # Kopieren des Originalbildes in das neue (kleine) Bild
  imagecopyresized($img2, $img, 0, 0, 0, 0, $nw, $nh, $ow, $oh);
  
  # Das neue Bild ausgeben
  imagepng($img2);

  # freigeben des allokierten Speichers...
  imagedestroy($img);
  imagedestroy($img2);
?> 

Das nächste Codestück ist ähnlich. Aber hierbei wird das geladene PNG-Bild in der halben Größe als JPG Bild auf dem Server gespeichert. Diese Funktion kann man z.B. benutzen, wenn man automatisch Thumbnails erzeugen möchte um diese auf dem Server zu speichern.

<?php
  # gd06.php

  $img = imagecreatefrompng("gdlogobig.png");

  # Bildgröße ermitteln
  $ow = imagesx($img);
  $oh = imagesy($img);
  
  # Neue (halbe) Bildgröße berechnen
  $nw = round($ow / 2);
  $nh = round($oh / 2);

  # Neues Bild erzeugen
  $img2 = imagecreatetruecolor($nw, $nh);
  
  # Kopieren des Originalbildes in das neue (kleine) Bild
  imagecopyresized($img2, $img, 0, 0, 0, 0, $nw, $nh, $ow, $oh);
  
  # Das neue Bild ausgeben
  imagejpeg($img2, "gdlogosmall.jpg");

  # freigeben des allokierten Speichers...
  imagedestroy($img);
  imagedestroy($img2);

  echo '<img src="gdlogosmall.jpg" alt="erzeugtes Bild" />';
?> 

Zeichnen mit der gdLib

Es gibt innerhalb der gdLib viele Zeichenfunktionen, womit man auf die Ressource zeichnen kann. Es folgt ein kleines Beispiel.

Wir erzeugen uns ein leeres PNG-Bild (Hintergrund schwarz) und holen uns als erstes eine Zeichenfarbe in eine Variable $clr mit dem Befehl imagecolorallocate();. Man gibt als erstes die Ressource an und danach 3 Farbangaben (R,G,B).

Um ein gefülltes Rechteck zu zeichnen gibt es den Befehl imagefilledrectangle(); in dem man die Ressource, die Koordinaten für Oben-Links, Unten-Rechts und die Farbe übergibt.

Jetzt zeichnen wir uns einen einfachen Kreis in der Farbe Rot. Wir setzen wieder unsere Zeichenfarbe und benutzen den Befehl imagearc();. Dabei sollte man drauf achten, dass der Befehl den Teil von-bis Winkel als Ellipse zeichnet. In diesem Beispiel ist der Kreismittelpunkt bei den Koordinaten (70, 50) und die Höhe und Breite des Kreises ist jeweils 60px und er zeichnet einen vollen Kreis vom Winkel 0 - 360.

Zum Schluss zeichnen wir ein gefülltes Dreieck als Polygon. Es wird ein Array von Punkten angelegt, das fortlaufend die X- und Y-Koordinaten der Punkte enthält (Px1 = [0]; Py1 = [1]; Px2 = [2]; Py2 = [3]; ...). Der Befehl imagefilledpolygon(); erwartet, wie bei allen Zeichenfunktionen als erstes die Zielressource, danach das Array mit den Punkten, die Anzahl der Punkte und die Füllfarbe.

<?php
  # gd07.php

  # festlegen, was fuer ein Bild dargestellt werden soll
  header("Content-type: image/png");

  # Bild erzeugen
  $img = imagecreatetruecolor(200, 100);

  # Neue Zeichenfarbe setzen
  $clr = imagecolorallocate($img, 0, 200, 0);

  # Ein gefuelltes Rechteck malen in der neuen Zeichenfarbe
  imagefilledrectangle($img, 10, 10, 30, 90, $clr);

  # Einen Kreis Zeichen (nicht gefuellt);
  $clr = imagecolorallocate($img, 200, 0, 0);
  imagearc($img, 70, 50, 60, 60, 0, 360, $clr);

  # Einen gefuellten Polygon zeichnen
  $clr = imagecolorallocate($img, 50, 50, 250);
  $points = array(150, 10, 110, 80, 190, 80);
  imagefilledpolygon($img, $points, (sizeof($points) / 2), $clr);

  # Bild ausgeben
  imagepng($img);

  # freigeben des allokierten Speichers
  imagedestroy($img);
?> 

Bild-Transparenz und Overlay-Funktionen

Einfache Overlay-Funktionen

Mit den Overlay-Funktionen kann man mehrere Ressourcen übereinander legen. Hierbei ist es sogar möglich, einen Alpha-Effekt zu nutzen, der das obere Bild durchsichtig machen kann. An einem Beispiel wird gezeigt, wie man ein durchsichtiges Wasserzeichen in einem Foto einfügt.

Man muss das Foto und das Wasserzeichen jeweils in eine Ressource laden. Danach werden die Größen ermittelt, um später die Position des Wasserzeichens im Bild festzulegen. Um nun das Wasserzeichen auf das Bild zu legen brauchen wir die Funktion imagecopymerge();. Der erste Parameter ist die Quellressource, in diesem Fall das Foto. Der zweite Parameter ist die Ressource vom Wasserzeichen. Danach kommen die Koordinaten (X,Y) der linken oberen Ecke, wo das Wasserzeichen anfangen soll im Zielbild. Jetzt müssen die Anfangskoordinaten im Wasserzeichen-Bild angegeben werden mit Breite und Höhe. Da hier das ganze Bild genutzt werden soll, sind die Startkoordinaten 0,0 gefolgt von der Breite und Höhe. Zum Schluss wird der Wert für Alpha festgelegt. Das Wasserzeichen wird mit 25% Sichtbarkeit auf das Foto gelegt.

<?php
  # gd08.php

  # festlegen, was fuer ein Bild dargestellt werden soll
  header("Content-type: image/png");

  # Bild laden
  $img = imagecreatefromjpeg("eStudyFun.jpg");
 
  # Bildgroesse ermitteln
  $picw = imagesx($img);
  $pich = imagesy($img);

  # Wasserzeichen laden
  $img2 = imagecreatefromgif("logo_estudy.gif");
 
  # Bildgroesse ermitteln
  $thumbw = imagesx($img2);
  $thumbh = imagesy($img2);

  # Erstes Bild in das zweite Bild kopieren
  imagecopymerge($img, $img2, 5, ($pich-5-$thumbh), 0, 0, $thumbw, $thumbh, 25);

  # Bild ausgeben
  imagepng($img);

  # freigeben des allokierten Speichers
  imagedestroy($img);
  imagedestroy($img2);
?> 

Transparente Flächen festlegen

Transparente Flächen bieten auch in der gdLib sehr viele Möglichkeiten zur Bilderzeugung. Man kann verschiedene Grafiken, Bilder so zusammenlegen oder, wie im Abschnitt FotoForum noch beschrieben, nützliche Effekte erzeugen. Ein kleines Beispiel soll verdeutlichen, wie einfach die Transparenz ausgenutzt werden kann um neue Grafiken (in diesem Fall ein Logo) zu erstellen.

Wir nehmen das gdLib-Logo, was als PNG-Datei auf dem Server liegt, und laden es in eine Bildressource. Jetzt muss man eine Farbe festlegen, welche später als Transparenz verwendet wird. Zum Festlegen benutzt man die Funktion imagecolortransparent();. Man übergibt als ersten Parameter die Bildressource und dann die transparente Farbe. Im Beispiel erzeugen wir noch eine zweite Ressource der gleichen Größe, die standardmäßig eine schwarze Hintergrundfarbe hat. Das erste und zweite Bild wird nun mit imagecopymerge(); zusammengeführt. Danach hat man das gdLib-Logo mit schwarzem Hintergrund.

<?php
  # gd09.php

  # festlegen, was fuer ein Bild dargestellt werden soll
  header("Content-type: image/png");

  # Bild laden
  $img = imagecreatefrompng("gdlogobig.png");
 
  # Farbe auf weiss setzen
  $clr = imagecolorallocate($img, 255, 255, 255);
  
  # Bildtransparenz setzen (weiss ist transparent)
  imagecolortransparent($img, $clr);

  # Bildgroesse ermitteln
  $ow = imagesx($img);
  $oh = imagesy($img);

  # Zweites Bild erzeugen
  $img2 = imagecreatetruecolor($ow, $oh);
 
  # Erstes Bild in das zweite Bild kopieren
  imagecopymerge($img2, $img, 0, 0, 0, 0, $ow, $oh, 100);

  # Bild ausgeben
  imagepng($img2);

  # freigeben des allokierten Speichers
  imagedestroy($img);
  imagedestroy($img2);
?> 

Anwendungsgebiete in eStudy

Thumbnail-Erzeugung

Im Laufe der Überarbeitung des Portals wurden Module zum Teil so umgestellt, dass Bilder nicht mehr mit Hilfe des <img />-Tags "verkleinert" angezeigt werden, sondern ein Thumbnail bei Laufzeit erzeugt wird. Dies hat den Vorteil, dass man auch wirklich nur das Bild in der Größe des Thumbnails herunterladen muss und nicht das komplette Originalbild. Das hat in der Usergalerie dazu geführt, dass die Seiten ca. um den Faktor 10 schneller laden als zuvor.

Es wurde ein PHP-Skript implementiert, das je nach Bild ein Thumbnail erzeugt und ausgibt. Dieses Skript wird innerhalb des jeweiligen <img />-Tag als "src" angegeben mit der Bilddatei als Parameter und der maximalen Thumbnail-Höhe und -Breite.

Beispiel "src"-Angabe: http://estudy.mni.fh-giessen.de/common/makethumb.php?picurl=../upload/user/168/G5atSportsMart.jpg&maxw=125&maxh=170

FotoForum

Im FotoForum gibt es mehrere Funktionen, die auf der gdLib basieren. Es wurde ein "Crop-Tool" PHP-Skript geschrieben, das vor dem Speichern neuer Bilder dem User die Möglichkeit bietet, nicht benötigte Flächen vorher wegzuschneiden. Zur besseren Darstellung der wegfallenden Flächen wurde ein zweites Bild mit der gdLib erzeugt, das einen transparenten Bereich enthält und der Teil, der wegfällt, dort als roten Bereich zeichnet. Danach wurde für die Voransicht das Bild mit dem roten Bereich über das Originalbild mit einem Alpha-Effekt zusammengeführt.

Fotoforum.jpg

Dieser Effekt wurde nicht nur für das Hochladen neuer Bilder verwendet, sondern auch für die "Bildzitat-Funktion". Der Code und die Vorgehensweise sind die selben, nur dass hierbei die Koordinaten der oberen linken Ecke und unteren rechten Ecke abgespeichert werden und später im Forum dazu benutzt werden, um ein zugeschnittenes Thumbnail des Originalbildes zu erzeugen.

MapDesigner

Wie beim FotoForum wird das Bild-Crop-Skript ausgeführt beim Hochladen neuer Bilder, um nicht relevante Bildflächen wegzuschneiden und eine verkleinerte Kopie mit festgelegter maximaler Breite und Höhe der Maps auf den Server zu speichern.

Ansonsten wird die gdLib benutzt, um die Bilder verkleinert darzustellen, damit man diese innerhalb des Contentbereichs bearbeiten kann. Auf jeder Map werden bei der Bearbeitung sensitiver Flächen die bereits vorhandenen Flächen durch eine rote halbtransparente Fläche gekennzeichnet. Diese können je nach Art der Fläche ein Rechteck, Kreis oder ein Polygon sein.

Beim Erstellen neuer Flächen werden die ausgewählten Koordinaten mit einem kleinen roten Kreuz dargestellt. Je nach Form und Anzahl der Punkte wird eine Vorschau der neuen Fläche erzeugt. Hierzu wird ebenfalls das Thumbnail-PHP-Skript benutzt und mit speziellen Parametern aufgerufen.

Mapdesigner.jpg

Links und Quellen

Quellen und interessante Links zum Thema gdLib

Beispiele hier ausführbar - [1]

Offizielle gdLib-Seite - [2]

gdLib-Doc von php.net - [3]