# Dynamische Bildgenerierung – PHP‑Variante
Die Welterfahrung des Menschen schlägt sich in den bleibenden Gestalten der Musik, Literatur und Malerei nieder.
– Hans-Georg Gadamer, dt. Philosoph
Die Möglichkeit, mit PHP zur Laufzeit Grafiken zu erzeugen, hat ein breites Einsatzgebiet, so etwa grafische Schaltflächen, kleine Vorschaubilder (Thumbnails) oder Diagramme.
# Die GD-Library und PHP
Die GD-Library stellt in PHP alle wichtigen Funktionen für Grafiken und Bilder zur Verfügung. Auf diese Weise können Sie neue Grafiken auf Basis bereits existierender Grafiken oder vollständig neu erzeugen. Die GD-Library ist den PHP-Distributionen bereits als DLL beigelegt, muss jedoch zuvor erst aktiviert werden. Damit Sie nun nicht in jedem Script die entsprechende DLL (php_gd.dll) dynamisch laden müssen, ist es sinnvoll, das Laden der DLL bereits in der php.ini zu aktivieren.
Sie können die php.ini mit einem beliebigen Texteditor öffnen, da der Inhalt der Datei in reinem Text vorliegt und somit problemlos zu lesen ist. Diese Datei wird normalerweise im Verzeichnis C:\Windows abgelegt. Suchen Sie in der Datei die Zeile extension=php_gd.dll
. Wenn am Anfang der Zeile ein Semikolon steht, müssen Sie dieses entfernen. Fehlt das Semikolon, ist die GD-Library bereits aktiviert. Speichern Sie die vorgenommenen Änderungen an der php.ini ab.
Welche Grafikformate unterstützt werden, hängt jedoch von der Version der GD-Library ab. Bei Versionen, die älter als 1.6 sind, unterstützt die GD-Library das JPEG- und das GIF-Format. Aufgrund des Lizenzproblems mit dem GIF-Format wird bei neueren Versionen das GIF-Format nicht mehr unterstützt und stattdessen das PNG-Format verwendet.
Bei den aktuellen PHP-Versionen liegt die GD-Library meist in zwei verschiedenen Versionen vor: meistens in der Version 1.6.2 und in der Version 2.0+. Je nachdem, welche dieser beiden Versionen Sie verwenden möchten, müssen Sie eine andere Konfiguration in der php.ini vornehmen. Möchten Sie die Version 1.6 verwenden, müssen Sie, wie erwähnt, lediglich das Semikolon vor der Zeile extension=php_gd.dll
entfernen. Möchten Sie jedoch die Version 2.0+ verwenden, müssen Sie die Zeile extension=php_gd.dll
durch extension=php_gd2.dll
ersetzen (natürlich ohne Semikolon).
# Eine erste dynamische Grafik
Vor jeder Grafikoperation müssen Sie zuerst mit der Funktion imagecreate
eine leere Grafik erstellen. Die Funktion erwartet als Parameter die Breite und die Höhe der neuen Grafik in Pixel. Wenn die neue Grafik erzeugt werden konnte, liefert die Funktion einen Zeiger auf die Grafik zurück. Sie liefert FALSE
, falls die Grafik nicht erstellt werden konnte.
int imagecreate(int width, int heigth)
Ein Beispiel-Aufruf:
$image = imagecreate(175,25);
In der Variablen $image
wird ein Zeiger auf die neue Grafik gespeichert. Die neue Grafik ist 175 Pixel breit und 25 Pixel hoch.
# Farben
Zu Beginn ist die Farbpalette einer Grafik leer. Eine neue Farbe muss also zunächst definiert werden, damit sie in die Farbpalette der Grafik eingefügt wird. Dies ermöglicht die Funktion imageColorAllocate
. Als ersten Parameter erwartet sie den Zeiger auf die Grafik und anschließend die einzelnen Farbwerte der Farbe. Die Farbwerte werden als Zahlen zwischen 0 und 255 angegeben, wobei 0 für keinen Anteil steht und 255 für den maximalen Farbanteil. Die Funktion gibt anschließend die Farb-ID der Farbe in der Palette zurück.
php
int imageColorAllocate(int image, int red, int green, int blue)
Beispiele:
$white = imageColorAllocate($image,255,255,255);
$black = imageColorAllocate($image,0,0,0);
$red = imageColorAllicate($image,255,0,0);
$green = imageColorAllocate($image,0,255,0);
$blue = imageColorAllocate($image,0,0,255);
Durch dieses System stehen Ihnen 16,6 Millionen Farben zur Verfügung. Dies dürfte für eigentlich jede Grafik vollkommen ausreichend sein.
Die erste Farbe, die Sie definieren, wird als Hintergrundfarbe verwendet. Wenn Sie also in die Grafik zeichnen möchten, sollten Sie immer zwei Farben definieren, damit nicht alles in der gleichen Farbe wie der Hintergrund gezeichnet wird.
# Text einfügen
Die Funktion imageString
zeichnet eine Zeichenkette in eine Grafik.
int imageString(int image, int font, int x, int y, string str, int color)
Als ersten Parameter erwartet die Funktion den Zeiger auf die Grafik. Für den zweiten Parameter font
können Sie eine Zahl zwischen 1 bis 5 angeben. Diese Werte stehen für interne Zeichensätze, die die GD-Library zur Verfügung stellt. Zwar können Sie auch andere Schriftarten wie z. B. TrueType-Schriften verwenden, damit werden Sie sich aber erst später beschäftigen. Die Parameter x
und y
definieren die Position, an der die Zeichenkette eingefügt wird. x
gibt die horizontale und y
die vertikale Position an. Dabei steht (0,0) für die linke obere Ecke. Die einzufügende Zeichenkette wird als Parameter str
übergeben und die Farbe, in der die Zeichenkette dargestellt werden soll, als Parameter color
.
imageString($image,5,50,10,'Test',$black);
Dieses Beispiel fügt nun die Zeichenkette Test
in der Farbe Schwarz an der Position (50,10) in die Grafik ein. Der gewählte Zeichensatz ist 5.
Es gibt jedoch etwas zu beachten: An der Position, die Sie mit den Parametern x
und y
an die Funktion übergeben, wird die linke obere Ecke des auszugebenden Textes ausgerichtet. Um eine Zeichenkette nun sowohl horizontal als auch vertikal zentriert in der Grafik auszugeben, müssen Sie die x- und die y-Position zuvor abhängig von der Zeichenkettenlänge und -höhe errechnen.
Es gibt zwei Funktionen, die die Höhe und die Breite eines einzelnen Zeichens ermitteln. Dies sind imageFontWidth
und imageFontHeight
. Beide Funktionen erwarten lediglich den Zeichensatz, dessen Höhe und Breite ermittelt werden soll. Die Höhe und Breite wird dann von den Funktionen in Pixel zurückgegeben.
int imageFontHeight(int font)
int imageFontWidth(int font)
Die Höhe einer einzeiligen Zeichenkette lässt sich sehr einfach berechnen:
$str_height = imageFontHeight(5);
Bei der Länge der Zeichenkette muss zusätzlich noch die Anzahl der Zeichen berücksichtigt werden. Diese erhalten Sie mit der Funktion strLen
.
$str_width = imageFontWidth(5) * strLen('Test');
Nach dieser Vorarbeit ist das zentrierte Positionieren der Zeichenkette kein Problem mehr. Von der Breite der Grafik wird die Breite der Zeichenkette in Pixel abgezogen und von der Höhe der Grafik die Höhe der Zeichenkette. Beide Werte müssen lediglich noch durch 2 geteilt werden.
$str_x = (175 – $str_width) / 2;
$str_y = (25 – $str_height) / 2;
# Ausgabe des Bildes
Wenn Sie alle Änderungen an der Grafik durchgeführt haben, müssen Sie die Grafik natürlich noch ausgeben. Dies ermöglichen die Funktionen imagePng
und imageJPEG
. Welche der beiden Sie verwenden, hängt davon ab, in welchem Format Sie die Grafik ausgeben möchten. Soll die Datei im PNG-Format ausgegeben werden, müssen Sie die Funktion imagePng
benutzen, und für die Ausgabe im JPEG-Format verwenden Sie die Funktion imageJPEG
. Beide Funktionen erwarten als ersten Parameter auf jeden Fall den Zeiger auf die Grafik. Der zweite Parameter ist optional und gibt einen Dateinamen an, unter dem die Grafik gespeichert wird. Geben Sie den Parameter nicht an, wird die Grafik im Browser ausgegeben. Wird der Parameter angegeben, erfolgt die Ausgabe in der angegebenen Datei.
int imagePng(int image [, string filename])
int imageJPEG(int image [, string filename [, int quality]])
Wenn Sie die Grafik im JPEG-Format ausgeben und außerdem als Datei speichern, können Sie zusätzlich noch die Qualität der Grafik in Prozent angeben. Möchten Sie die Qualität festlegen, die Grafik aber im Browser ausgeben, müssen Sie als Dateinamen eine leere Zeichenkette übergeben.
imagePng($image,"/images/tmp_image.png");
imageJPEG($image,"/images/tmp_image.jpg",75);
In beiden Beispielen wird die erzeugte Grafik im Verzeichnis images gespeichert. Bei der Speicherung als JPEG-Grafik wurde als Qualität 75 % angegeben.
Zur Ausgabe im Browser müssen Sie zusätzlich noch den MIME-Typ ausgeben, ähnlich wie bei PDF-Dokumenten. Der MIME-Typ für PNG-Grafiken lautet image/png
und für JPEG-Grafiken image/jpg
.
Vor dem Aufruf einer der beiden Funktionen sollten Sie den entsprechenden MIME-Typ ausgeben, falls die Ausgabe im Browser erfolgen soll. Also
header('Content-Type: image/png');
oder
header('Content-Type: image/jpg');
Nachdem die Grafik dann im Browser ausgegeben worden ist, ist es auf jeden Fall ratsam, den durch die Grafik belegten Speicher wieder freizugeben. Die Freigabe erfolgt durch den Aufruf der Funktion imageDestroy
. Als Parameter müssen Sie lediglich den Zeiger auf die Grafik übergeben.
int imageDestroy(int image)
Als zusammenhängendes Script könnte dies folgendermaßen aussehen:
<?php
$width = 175;
$height = 25;
$font = 5;
$str = 'Ein Text';
$image = imageCreate($width,$height);
$yellow = imageColorAllocate($image,255,255,0);
$blue = imageColorAllocate($image,0,0,255);
$str_x = ($width - (imageFontWidth($font) * strLen($str))) / 2;
$str_y = ($height - imageFontHeight($font)) / 2;
imageString($image,$font,$str_x,$str_y,$str,$blue);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.1: Ausgabe einer Grafik mit Schriftzug
Da die Breite und Höhe der Grafik sowie der gewählte Schriftzug und die Zeichenkette mehrmals im Script benötigt werden, wurden zu Beginn des Scripts vier Variablen mit den entsprechenden Werten definiert. Anschließend wird die Grafik erzeugt, und der Zeiger in der Variablen $image
gespeichert. Im nächsten Schritt werden zwei Farben definiert. Die erste Farbe wird automatisch als Hintergrundfarbe verwendet. Damit die Zeichenkette sowohl horizontal als auch vertikal zentriert ausgegeben wird, werden in den Variablen $str_x
und $str_y
die berechneten x- und y-Koordinaten gespeichert. Dann wird die Zeichenkette in die Grafik eingefügt. Anschließend wird an den Browser der entsprechende MIME-Typ gesendet, die Grafik ausgegeben und der belegte Speicher schlussendlich freigegeben. Im Browser sieht das dann wie in Abbildung 1.1 gezeigt aus.
Abbildung 1.1: Mit PHP erzeugte Grafik
# Grafiken verändern
Neben der Möglichkeit, eine vollständig neue Grafik zu erstellen, können Sie auch eine Grafik auf Basis einer bereits existierenden erzeugen. Anstelle der Funktion imageCreate
müssen Sie dann jedoch eine der spezielleren Funktionen verwenden. Welche Funktion Sie dann genau wählen, hängt vom Format der Basisgrafik ab. Liegt die Grafik im JPEG-Format vor, müssen Sie die Funktion imageCreateFromJPEG
und bei PNG die Funktion imageCreateFromPng
verwenden.
Als Parameter müssen Sie selbstverständlich den Dateinamen übergeben, unabhängig davon, welche Funktion Sie verwenden. Anschließend erhalten Sie einen Zeiger auf die neue Grafik.
int imageCreateFromJPEG(string filename)
int imageCreateFromPng(string filename)
Konnte die Datei nicht geöffnet werden, liefern beide Funktionen eine leere Zeichenkette zurück.
$image = imageCreateFromJPEG('basejpeg.jpg');
$image = imageCreateFromPng('basepng.png');
Überprüfen Sie vor weiteren Manipulationen an der Grafik den Rückgabewert der Funktion. Konnte die Grafik nicht geladen werden, wird eine Fehlermeldung erzeugt, die vom Browser als Verbindungsabbruch interpretiert wird. In einem solchen Fall sollten Sie eine leere Grafik erzeugen. Mögliche Fehlermeldungen können Sie dann mit dem @
vor der Funktion unterdrücken. Mit einer einfachen if
-Anweisung lässt sich ein Fehler beim Öffnen der Basisgrafik behandeln.
$image = @imageCreateFromPNG('basepng.png');
if(!$image)
{
$image = imageCreate(175,25);
$bg = imageColorAllocate($image,51,102,153);
}
Für den Fall, dass die Grafik basepng.png nicht geöffnet werden konnte (aus welchem Grund auch immer), wird im nachfolgenden if
-Anweisungsblock eine leere Grafik mit Hintergrundfarbe definiert. Sollten danach Manipulationen an der Grafik erfolgen, ist dies nicht weiter tragisch, da diese dann lediglich auf einem einfachen Hintergrund und nicht auf Basis einer Grafik erfolgen.
# Abmessungen
Wenn Sie eine Grafik als Basis einer neuen verwenden, heißt das nicht, dass Sie zuvor auch die exakten Abmessungen der Basisgrafik kennen. Denn eine neue Grafik, die auf einer vorhandenen basiert, erhält dieselben Abmessungen wie die ursprüngliche. Um die Breite und Höhe ermitteln zu können, stehen die Funktion imagesx
und imagesy
zur Verfügung. imagesx
ermittelt die Breite der neuen Grafik und imagesy
die Höhe. Beide Werte entsprechen den Abmessungen in Pixel. Als Parameter erwarten beide Funktionen den Zeiger auf die Grafik.
int imagesx(int image)
int imagesy(int image)
Im folgenden Listing werden die zuvor genannten Funktionen verwendet, um auf Basis einer existierenden Grafik eine neue zu erstellen. Zusätzlich wird ein Text exakt in der Mitte der Grafik ausgegeben.
<?php
$font = 5;
$str = 'Schaltfläche';
$image = @imageCreateFromPng('basepng.png');
if(!$image)
{
$image = imageCreate(175,25);
$blue = imageColorAllocate($image,51,102,153);
}
$white = imageColorAllocate($image,255,255,255);
$str_x = (imagesx($image) - (imageFontWidth($font) * strLen($str))) / 2;
$str_y = (imagesy($image) - imageFontHeight($font)) / 2;
imageString($image,$font,$str_x,$str_y,$str,$white);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.2: Neue Grafik mit Text auf Basis einer existierenden Grafik
Nach der Definition der Variablen $font
und $str
wird versucht, eine neue Grafik zu erstellen, die auf der Grafik basepng.png basieren soll. Tritt dabei ein Fehler auf, wird einfach eine leere Grafik erzeugt, die eine blaue Hintergrundfarbe erhält. Die Position, an der die Zeichenkette eingefügt werden soll, wird mit den Funktionen imagesx
und imagesy
berechnet. Die Ausgabe im Browser ist in Abbildung 1.2 dargestellt.
Abbildung 1.2: Ausgabe des Scripts aus Listing 1.2 im Browser
# Zeichnen
Das Einfügen von Text in eine Grafik ist natürlich nur eine der Möglichkeiten, die Ihnen zur Verfügung stehen. Sie können auch Formen wie Rechtecke, Kreise oder Linien in die Grafik zeichnen.
# Punkte und Linien
Zwei der einfachsten Formen, die Sie in eine Grafik einfügen können, sind Punkte und Linien. Bei Punkten wird an einer beliebigen Stelle die Farbe eines Pixels verändert. Einen Punkt bzw. einen Pixel zu setzen, ermöglicht die Funktion imagesetpixel
. Als Parameter erwartet sie sowohl den Zeiger auf die Grafik als auch die x/y-Position, an der die Farbe des Pixels verändert werden soll. Die neue Farbe wird als letzter Parameter übergeben.
int imagesetpixel(int image, int x, int y, int color)
Ein Beispiel:
$red = imagecolorallocate($image,80,0,0);
for($i = 10; $i < 110; $i++)
{
imagesetpixel($image,$i,15,$red);
}
Dieses Beispiel würde insgesamt 100 Pixel auf die Farbe Rot setzen. Da die veränderten Pixel hintereinander auf einer Höhe liegen, kann man eine solche Schleife auch zum Zeichnen einer Linie verwenden. Einfacher wäre es jedoch, die entsprechende Funktion zu verwenden.
Die Funktionen imageline
und imagedashedline
zeichnen beide eine Linie in die Grafik, mit dem Unterschied, dass imagedashedline
eine gestrichelte Linie zeichnet und imageline
eine durchgezogene.
int imageline(int image, int x1, int y1, int x2, int y2, int color)
int imagedashedline(int image, int x1, int y1, int x2, int y2,
int color)
Um nun eine Linie zu zeichnen, müssen Sie zum einen den Zeiger auf die Grafik angeben und zum anderen den Start- und Endpunkt. Zusätzlich sollten Sie natürlich noch eine Farbe angeben. Die Start- und Endpunkte unterteilen sich dabei in die x- und y-Koordinaten.
<?php
$image = imageCreate(175,20);
$bg = imageColorAllocate($image,255,255,255);
$red = imageColorAllocate($image,255,0,0);
$green = imageColorAllocate($image,0,255,0);
$blue = imageColorAllocate($image,0,0,255);
for($i=10; $i<=165; $i++)
{
imageSetPixel($image,$i,5,$red);
}
imageLine($image,10,10,165,10,$green);
imageDashedLine($image,10,15,165,15,$blue);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.3: PHP-Script, das drei Linien auf unterschiedliche Weise im Browser ausgibt
In Listing 1.3 werden vier Farben definiert; eine für den Hintergrund und drei zum Zeichnen. Anschließend wird eine Linie in der Farbe Rot gezeichnet, indem einfach mehrere Pixel hintereinander auf die Farbe gesetzt werden. Danach wird eine Linie in Grün vom Punkt (10,10) zum Punkt (165,10) gezeichnet. Es folgt eine weitere, diesmal gestrichelte Linie vom Punkt (10,15) zum Punkt (165,15). Zum Schluss wird die Grafik im Browser ausgegeben.
Im Browser sieht das dann folgendermaßen aus:
Abbildung 1.3: Ausgabe des Listing 1.3 im Browser
# Rechtecke
Auch für die Grundform Rechteck existieren zwei Funktionen: imageRectangle
und imageFilledRectangle
. Während imageRectangle
nur den Rahmen eines Rechtecks zeichnet, erzeugt imageFilledRectangle
ein flächiges Rechteck.
int imageRectangle(int image, int x1, int y1, int x2, int y2, int color)
int imageFilledRectangle(int image, int x1, int y1, int x2, int y2, int color)
Neben dem Zeiger auf die Grafik erwarten die Funktionen natürlich noch weitere Parameter: zum einen die beiden Eckpunkte links oben (x1,y1) und rechts unten (x2,y2) und zum anderen die Farbe für die Linie bzw. die Fläche.
<?php
$image = imageCreate(200,100);
$bg = imageColorAllocate($image,0,0,0);
$yellow = imageColorAllocate($image,255,255,0);
imageRectangle($image,10,10,90,90,$yellow);
imageFilledRectangle($image,110,10,190,90,$yellow);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.4: PHP-Script, das zwei Rechtecke in eine Grafik zeichnet
Das PHP-Script aus Listing 1.4 zeichnet zwei verschiedene Rechtecke in eine Grafik, einmal ein Rechteck nur mit Außenlinie und einmal ein gefülltes Rechteck.
Abbildung 1.4: Ausgabe des Listing 1.4 im Browser
# Kreise und Kreisbögen
Die beiden Funktionen imageEllipse
und imageFilledEllipse
ermöglichen das Zeichnen einer Ellipse bzw. eines Kreises. Wie auch schon bei Rechtecken stehen Ellipsen mit Außenrand und gefüllte Ellipsen zur Verfügung.
int imageEllipse(int image, int x, int y, int width, int height,int color)
int imageFilledEllipse(int image, int x, int y, int width, int height, int color)
Die beiden Parameter x
und y
zentrieren die Ellipse an der angegebenen Position in der Grafik. Mit width
bestimmen Sie die Breite und mit height
die Höhe der Ellipse. color
definiert die Farbe, in der die Ellipse gezeichnet werden soll. Leider funktioniert die Funktion erst mit der GD-Version 2.0.2+. Daher wird im folgenden Listing lediglich die Funktion imageFilledEllipse
verwendet.
<?php
$image = imageCreate(300,200);
$bg = imageColorAllocate($image,0,0,0);
$yellow = imageColorAllocate($image,255,255,0);
imageFilledEllipse($image,50,50,90,90,$yellow);
imageFilledEllipse($image,150,50,90,90,$yellow);
imageFilledEllipse($image,100,150,180,90,$yellow);
imageFilledEllipse($image,250,100,90,180,$yellow);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.5: Ausgabe von Kreisen und Ellipsen in eine Grafik
Nach den obligatorischen Definitionen der neuen Grafik und der Farben werden mit der Funktion imageFilledEllipse
zwei Kreise und zwei Ellipsen in die Grafik eingefügt.
Abbildung 1.5: Ausgabe des Listing 1.5
Es ist auch möglich, lediglich einen Kreisbogen zu zeichnen, und zwar mit der Funktion imageArc
. Diese Funktion erwartet jedoch sehr viele Parameter, zuallererst natürlich den Zeiger auf die Grafik. Anschließend folgen die Position in der Grafik, die als Mittelpunkt für den Kreisbogen verwendet werden soll, sowie die Breite und die Höhe. Zusätzlich folgen dann der Anfangs- und der Endwinkel sowie schlussendlich die Farbe.
int imageArc(int image, int x, int x, int width, int height, int start_ang, int end_ang, int color)
Die Winkel können mit einer Zahl zwischen 0 und 360 angegeben werden, wobei 0 rechts, 90 unten, 180 links und 270 oben ist. Das folgende Beispiel soll dies verdeutlichen.
<?php
$image = imageCreate(300,200);
$bg = imageColorAllocate($image,0,0,0);
$yellow = imageColorAllocate($image,255,255,0);
imageArc($image,100,100,150,150,180,270,$yellow);
imageArc($image,200,100,150,150,0,180,$yellow);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.6: Zeichnen von zwei Kreisbögen
In Listing 1.6 werden zwei Kreisbögen in die Grafik gezeichnet. Der erste Kreisbogen besitzt seinen Mittelpunkt an den Koordinaten (100,100). Die Breite und Höhe des fiktiven Kreises bzw. der Ellipse, von der dieser Kreisbogen stammt, beträgt jeweils 150 Pixel. Der Ausschnitt, den der Kreisbogen darstellt, reicht vom Winkel 180 bis zum Winkel 270. Dies entspricht einem Viertel. Der zweite Kreisbogen erhält den Mittelpunkt (200,100) und ebenfalls die Abmessungen von je 150 Pixel Breite und Höhe. Als Ausschnitt wurde diesmal der Bereich von 0 bis 180 gewählt, also die Hälfte. Im Browser sieht das dann so wie in Abbildung 1.6 dargestellt aus.
Abbildung 1.6: Ausgabe des Listing 1.6 im Browser
Obwohl die Funktion imageEllipse
erst ab der Version 2.0.2+ zur Verfügung steht, können Sie dieses Problem mit der Funktion imageArc
umgehen. Als Startwinkel müssen Sie einfach nur 0 und als Endwinkel 360 angeben, und schon erhalten Sie einen Kreis bzw. eine Ellipse nur mit Außenrand.
imageArc(50,50,90,90,0,360,$yellow);
// Zeichnet einen Kreis nur mit Außenrand
imageArc(100,50,180,90,0,360,$yellow);
// Zeichnet eine Ellipse nur mit Außenrand
# Flächen füllen
Die Funktion imageFill
in Verbindung mit Formen, die nur einen Außenrand besitzen, ermöglicht verschiedene Effekte. Unter anderem können Sie dadurch eine Form mit einem andersfarbigen Rahmen versehen. Die Funktion imageFill
füllt einen Bereich mit einer neuen Farbe. Alle Pixel, die dieselbe Farbe haben wie der Startpixel, werden mit der neuen Farbe versehen.
int imageFill(int image, int x, int x, int color)
Im folgenden Listing wird diese Möglichkeit dazu verwendet, einen Kreis, der nur einen Außenrand besitzt, mit einer anderen Farbe einzufärben.
<?php
$image = imageCreate(300,200);
$bg = imageColorAllocate($image,0,0,0);
$yellow = imageColorAllocate($image,255,255,0);
$orange = imageColorAllocate($image,255,150,0);
imageArc($image,150,100,90,90,0,360,$yellow);
imageFill($image,150,100,$orange);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.7: Füllen eines Kreises mit einer Farbe
Zuerst wird ein Kreisbogen gezeichnet und anschließend die Funktion imageFill
ausgeführt. Da der Startpunkt von imageFill
innerhalb des Kreises liegt, werden alle Pixel mit der Farbe Schwarz durch die neue Farbe ersetzt, und zwar nur bis zum Rand des Kreises.
Abbildung 1.7: Ausgabe des Listing 1.7 im Browser
# Transparenz
Grafiken, die mit der Funktion imageCreate
erstellt werden, besitzen eine 8-Bit-Farbpalette. Es stehen Ihnen also 256 Farben zur Verfügung. Mit imageCreateTrueColor
erstellen Sie eine neue Grafik mit einer TrueColor-Palette. Das Besondere daran ist, dass Ihnen nun auch Transparenz zur Verfügung steht. Eine Farbe besteht dann aus vier Teilen: Rot, Grün, Blau und Alpha (Transparenzgrad). Dieser Transparenzgrad kann zwischen 0 und 127 liegen, wobei 0 für keine Transparenz und 127 für durchsichtig steht.
resource imageCreateTrueColor(int width, int height)
Da eine TrueColor-Palette fest definiert ist, müssen Sie sich mit der Funktion imageColorResolveAlpha
den Index der Farbe, die Sie verwenden möchten, auslesen lassen. Die Funktion erwartet als Parameter den Zeiger auf die Grafik und alle vier Farbanteile. Alternativ können Sie Farben, die nicht transparent werden sollen, auch weiterhin mit imageColorAllocate
definieren.
int imageColorResolveAlpha(int image, int red, int green, int blue, int alpha)
Nun fehlt nur noch eine dritte Funktion, mit der Sie die Transparenz aktivieren oder deaktivieren können: imageAlphaBlending
. Diese Funktion erwartet als Parameter den Zeiger auf die Grafik und entweder TRUE
oder FALSE
. Wenn die Transparenz aktiviert werden soll, müssen Sie TRUE
übergeben. Zum Deaktivieren übergeben Sie FALSE
.
int imageAlphaBlending(int image, boolean alphamode)
<?php
$image = imageCreateTrueColor(300,200);
imageAlphaBlending($image,true);
$bg = imageColorAllocate($image,0,0,0);
$yellow = imageColorAllocate($image,255,255,0);
$blue = imageColorResolveAlpha($image,0,0,255,50);
imageFilledEllipse($image,100,100,150,150,$yellow);
imageFilledRectangle($image,150,50,250,150,$blue);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.8: Grafik mit TrueColor-Palette
Die Ausgabe des Listing 1.8 mit deaktivierter Transparenz zeigt Ihnen Abbildung 1.8 auf der linken Seite. Die Ausgabe im Browser, wenn Sie die Transparenz aktivieren (imageAlphaBlending($image,true)
), finden Sie auf der rechten Seite der Abbildung 1.8.
Abbildung 1.8: Ausgabe des Listing 1.8 mit deaktivierter (links) und aktivierter Transparenz (rechts)
# Erweiterte Textausgabe
Intern kennt die GD-Library fünf verschiedene Schriften, deren Unterschiede sich jedoch auf die Größe und Schriftdicke beschränken. Abbildung 1.9 zeigt eine Übersicht dieser Schriftvarianten.
Abbildung 1.9: Die fünf internen Schriftvarianten
Es gibt jedoch die Möglichkeit, auch andere Schriftarten zu verwenden. Dies können entweder Bitmap- oder TrueType-Fonts sein. Bitmap-Fonts werden mit der Funktion imageLoadFont
geladen. Da das Format der Bitmap-Fonts jedoch binären Abhängigkeiten unterliegt, müssen Sie die Schriften auf dem System erstellen, auf dem Sie die Schrift verwenden wollen. Es ist also sinnvoller, TrueType-Fonts zu verwenden.
Diese werden mit der Funktion imageTTFText
verwendet und ersetzen die Funktion imageString
. Da die Funktion imageTTFText
eine Menge Parameter kennt, folgt zuerst die Syntax:
int imageTTFText(int image, int size, int angle, int x, int y, int color, string fontfile, string text)
Als Parameter image
müssen Sie wie immer den Zeiger auf die Grafik angeben. Als size
geben Sie die Größe der Schrift in Pixel an. angle
ist der Winkel, in dem die Schrift ausgegeben werden soll. Er wird in Grad angegeben. 0 oder 360 entspricht dabei rechts (3 Uhr), 90 ist unten (6 Uhr), 180 ist links (9 Uhr) und 270 ist oben (12 Uhr). Die Parameter x
und y
definieren die Position, an der der Text platziert werden soll. color
kann eine beliebige Farbe sein, die mit imageColorAllocate
oder imageColorResolveAlpha
ermittelt wurde. Die TrueType-Schrift, in der der Text gezeichnet werden soll, wird als Parameter fontfile
angegeben. Benötigt werden dabei der Pfad und der Name der Datei. TrueType-Schriften enden in der Regel auf .ttf. Schlussendlich wird der auszugebende Text als Parameter text
übergeben.
Um diese Funktion jedoch verwenden zu können, muss die GD-Library in der Version 2.x installiert und das Modul FreeType eingebunden sein (in der GD-Library). Falls Sie Zweifel haben, ob dies bei Ihnen der Fall ist, sollten Sie die Funktion phpinfo
aufrufen und unter GD nachsehen, ob die Unterstützung aktiviert ist.
Das folgende Listing gibt einen Text in der Schriftart Arial aus:
<?php
$image = imageCreate(400,100);
$bg = imageColorAllocate($image,255,255,255);
$black = imageColorAllocate($image,0,0,0);
imageTTFText($image,50,0,25,25,$black,'arial','Arial');
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.9: Ausgabe eines Textes mit einer TTF-Schrift
Abbildung 1.10: Ausgabe des Listing 1.9
Die Ausgabe in Abbildung 1.11 wurde erzeugt, indem der Winkel der Schrift auf 90 gesetzt wurde.
imageTTFText($image,50,90,25,25,$black,'verdana.ttf','Verdana');
Abbildung 1.11: Um 90 Grad gedrehter Text
Dieser Effekt lässt sich auch auf die interne Schrift der GD-Library anwenden. Die Funktion imageStringUp
zeichnet einen String dann vertikal.
int imageStringUp(int image, int font, int x, int y, string text, int color)
Bei der Angabe der Koordinaten x und y müssen Sie beachten, dass an den angegebenen Werten die linke untere Ecke der Zeichenkette beginnt (aus vertikaler Sicht betrachtet). Das folgende Listing ist ein Beispiel für diese Funktion:
<?php
$image = imageCreate(50,120);
$text = 'vert. Text';
$bg = imageColorAllocate($image,255,255,255);
$black = imageColorAllocate($image,0,0,0);
$str_x = 10 + imageFontWidth(5) * strLen($text);
imageStringUp($image,5,10,$str_x,$text,$black);
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.10: Ausgabe einer Zeichenkette in vertikaler Richtung
Damit der String in der Grafik vollkommen zu sehen ist, wurde die y-Koordinate abhängig von der gewählten Schrift und Länge der Zeichenkette berechnet.
Abbildung 1.12: Ausgabe des Listing 1.10 im Browser
# Thumbnails erzeugen
Häufig wird die GD-Library auf Webseiten verwendet, um so genannte Thumbnails zu erzeugen. Dies sind Miniaturversionen von Bildern, die als Vorschau verwendet werden. Bei Galerien mit großen und ladeintensiven Bildern bieten sie dem Benutzer eine Orientierungshilfe. Er kann auf die Vorschau klicken und erhält die große Version. Die einfachste Möglichkeit wäre nun, in einem HTML-Dokument die Größe der Bilder auf 100 Pixel zu setzen, was aber dazu führt, dass alle Bilder zuvor in der Originalgröße geladen werden müssen. Die zu ladende Datenmenge verringert sich dadurch aber nicht. Besitzer eines Analogmodems werden Ihnen alles andere als dankbar sein, auch wenn die Großansichten der Bilder später umso schneller dargestellt werden. Die Geduld, die der User zuvor aufbringen muss, steht dazu in keinerlei Verhältnis, wenn er vorab mehrere Minuten warten muss, ehe die Bilder vollständig heruntergeladen sind.
Sehr viel besser wäre es, die Bilder noch auf dem Server zu verkleinern und so mit einer geringeren Größe an den Benutzer zu senden. Mit der GD-Library ist das ohne Probleme möglich.
Die Vorgehensweise ist dabei sehr einfach. Zuerst wird das Originalbild geöffnet und anschließend in eine neue Grafik kopiert. Beim Kopieren wird das Originalbild verkleinert. Das verkleinerte Bild wird dann an den Browser gesendet.
Die wichtigste Funktion zum Erzeugen von Thumbnails ist imageCopyResized
. Sie kopiert das Originalbild und verkleinert es gleichzeitig.
int imageCopyResized(int dst_im, int src_im, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h)
Aufgrund der Vielzahl an Parametern werde ich zunächst Klarheit schaffen. Die Abkürzung dst
steht für »destination«, ins Deutsche übersetzt bedeutet dies »Ziel«. src
steht für »source« und bedeutet »Quelle«. Diese beiden Abkürzungen werden bei den Parametern verwendet, um unterscheiden zu können, welcher Parameter sich auf welches Bild bezieht.
Die beiden Parameter dst_im
und src_im
stehen jeweils für die beiden Grafiken. Der Zeiger auf die Originalgrafik wird als Parameter src_im
übergeben und der Parameter auf die neue Grafik als Parameter dst_im
.
Den zu kopierenden Original-Bildausschnitt geben Sie mit den Parametern src_x
, src_y
, src_w
und src_h
an. Die Form dieses Bildausschnitts ist rechteckig. Die linke obere Ecke des Ausschnitts wird durch src_x
und src_y
definiert. Die Ausmaße des Ausschnitts, also die Breite und die Höhe, werden mit den Parametern src_w
und src_h
angegeben. Äquivalent dazu geben die Parameter dst_x
, dst_y
, dst_w
und dst_h
die Position und Größe des Ausschnitts in der Zielgrafik an. Je nachdem, ob der Zielbildausschnitt kleiner oder größer ist, wird der Originalausschnitt entweder gestaucht oder gestreckt.
imageCopyResized($image_dst,$image_src,10,10,50,50,100,50,50,25);
Dieser Beispielaufruf würde aus der Originalgrafik einen Ausschnitt von 50 × 25 Pixel kopieren, der an der Position (50,50) beginnt. Er wird dann in der Größe 100 × 25 an der Position (10,10) in die neue Grafik eingefügt. Der Ausschnitt wird also vergrößert.
<?php
/* Variablen setzen */
$src_file = $_GET['file'];
$max_w = 100;
$max_h = 100;
$dst_w = 0;
$dst_h = 0;
/* Dateityp ermitteln und öffnen */
$pos = strrpos($src_file,'.') + 1;
$file_ext = substr($file,$pos);
switch(strToLower($file_ext))
{
case 'png' :
$image_src = imageCreateFromPng($src_file);
break;
case 'jpg':
case 'jpeg':
$image_src = imageCreateFromJPEG($src_file);
break;
}
/* Bildgröße ermitteln */
$src_w = imagesx($image_src);
$src_h = imagesy($image_src);
/* Abmessungen festlegen */
if($src_w > $src_h)
{
$dst_w = $max_w;
$dst_h = $max_h / ($src_w / $src_h);
}
elseif($src_w < $src_h)
{
$dst_h = $max_h;
$dst_w = $max_w / ($src_h / $src_w);
}
else
{
$dst_h = $max_h;
$dst_w = $max_w;
}
/* Bild kopieren und ausgeben */
$image_dst = imageCreateTrueColor($dst_w,$dst_h);
imageCopyResized($image_dst,$image_src,0,0,0,0,$dst_w,$dst_h,$src_w,$src_h);
header('Content-Type: image/png');
imagePng($image_dst);
imageDestroy($image_src);
imageDestroy($image_dst);
?>
Listing 1.11: PHP-Script zum Erzeugen von Thumbnails
Das Listing 1.11 ist ein Beispiel dafür, wie die Funktion imageCopyResized
in einem Script-Kontext verwendet werden kann, um Thumbnails zu erzeugen. Zu Beginn werden erst einmal vier Variablen definiert. $src_file
erhält den in der URL als file
übergebenen Dateinamen der Grafik. Die Variable $max_px
definiert die maximale Breite und Höhe des Thumbnails. Die 100 Pixel sollten als Vorschau für ein Bild vollkommen ausreichend sein. Anschließend werden noch die Variablen $dst_w
und $dst_h
definiert und jeweils der Wert 0 zugewiesen. Diese Variablen erhalten später die errechneten Abmessungen des Thumbnails.
Im nächsten Teil des Scripts wird versucht, anhand des Dateinamens den Typ der Originalgrafik zu ermitteln, um ein Höchstmaß an Flexibilität bei den verwendbaren Grafiken zu ermöglichen. Die Funktion strrpos
liefert das letzte Vorkommen eines Zeichens innerhalb einer Zeichenkette. Dies wird verwendet, um die Endung der Datei ermitteln zu können. Da der Punkt dabei nicht erforderlich ist, wird 1 zu $pos
hinzuaddiert. Danach liefert die Funktion substr
von der angegebenen Position $pos
bis zum Ende alle Zeichen zurück. In der anschließenden switch
-Anweisung wird dann der Wert der extrahierten Zeichenkette unterschieden Je nachdem, welche Dateiendung es ist, wird entweder die Funktion imageCreateFromPng
oder imageCreateFromJPEG
zum Öffnen der Originalgrafik verwendet. Der Zeiger auf die Grafik wird in der Variablen $image_src
gespeichert.
Nachdem die Originalgrafik geöffnet worden ist, wird ihre Breite in der Variablen $src_w
und ihre Höhe in $src_h
gespeichert.
Das nun folgende if
-Konstrukt bewirkt, dass die Proportionen der Grafik auch als Thumbnail beibehalten werden können. Ist die Originalgrafik breiter als hoch, wird die Zielgrafik auf die maximale Breite ($max_px
) gesetzt. Die Höhe der Zielgrafik errechnet sich dann aus dem Verhältnis von Breite zu Höhe der Originalgrafik. Ist die Quellgrafik höher als breit, wird der Zielgrafik die maximale Höhe zugewiesen und die Breite anhand des Verhältnisses von Breite zu Höhe der Originalgrafik gesetzt. Sollte die Quellgrafik so breit wie hoch sein, wird der Zielgrafik die maximale Breite und maximale Höhe zugewiesen.
Nun wird die Zielgrafik erstellt. Da sowohl PNG- als auch JPG-Grafiken über mehr als 256 Farben verfügen, wird auch der Zielgrafik eine TrueColor-Palette zugewiesen, indem sie mit imageCreateTrueColor
erstellt wird. Als Größe werden die in $dst_w
und $dst_h
errechneten Werte verwendet. Anschließend wird die vollständige Originalgrafik kopiert und in der Größe an die Zielgrafik angepasst. Zum Schluss folgt die Ausgabe im Browser und die Freigabe der belegten Ressourcen.
Beachten Sie dabei, dass die Zielgrafik nicht von der Originalgrafik abhängig ist. Ob Sie nun JPG oder PNG verwenden, ist egal. Ich habe mich an dieser Stelle für PNG entschieden. Wenn Sie jedoch JPG verwenden, haben Sie die Möglichkeit, zusätzlich noch die Qualität der Grafik festzulegen und somit zusätzlich, wenn auch nur einige wenige, Bytes einzusparen.
In einem HTML-Dokument könnte das Script aus Listing 1.11 dann folgendermaßen verwendet werden:
<img src="thumbs.php?file=phpbig.png">
Natürlich wird hier davon ausgegangen, dass das Listing unter dem Namen thumbs.php gespeichert wurde. Die Abbildung 1.13 ist ein Screenshot eines HTML-Dokuments, das einmal die Grafik phpbig.png in der Originalgröße und einmal in der verkleinerten Version darstellt. Die verkleinerte Version wurde übrigens mit einem img
-Element und PHP-Scripts als Quelle eingebunden.
Abbildung 1.13: Thumbnails mit PHP
# Anwendungsbeispiele
Natürlich kann die GD-Library in Verbindung mit PHP auch zum Zeichnen von Diagrammen oder Ähnlichem verwendet werden. Dies gestaltet sich in den meisten Fällen jedoch etwas umständlich. Denn häufig müssen viele verschiedene Parameter berechnet und Abhängigkeiten für die Ausgabe in der Grafik gelöst werden.
# Kreisdiagramm
Die meisten Parameter müssen bei einem Balken- oder gar Säulendiagramm berechnet werden (wie z. B. die Eckpunkte, Abstände und Ähnliches), die wenigsten bei einem Kreisdiagramm. Dort ändert sich nämlich immer nur der Start- und Endwinkel.
Da die Funktion imageArc
für ein Kreisdiagramm nicht nutzbar ist (es zeichnet nur die Außenlinie), muss die Funktion imageFilledArc
verwendet werden. Diese Funktion zeichnet ein gefülltes Kreisstück.
int imageFilledArc(int image, int x, int y, int width, int height, int ang_start, int ang_end, int color, int style)
Als ersten Parameter erwartet die Funktion den Zeiger auf eine Grafik, der als image
übergeben wird, gefolgt vom Mittelpunkt des Kreises als Parameter x
und y
. Die Parameter width
und height
definieren die Breite und Höhe des Kreises, von dem das Kreisstück gezeichnet werden soll. ang_start
gibt den Startwinkel und ang_end
den Endwinkel des Kreisstücks an. Die Farbe des Segments wird als Parameter color
übergeben. Der letzte Parameter definiert den Stil des Kreissektors. Eine oder mehrere der folgenden Konstanten können eingesetzt werden.
IMG_ARC_PIE
Verbindet den Start- und Endwinkel als Bogen.IMG_ARC_CHORD
Verbindet den Start- und Endwinkel mit einer Geraden.IMG_ARC_NOFILL
Verhindert, dass das Kreisstück mit Farbe gefüllt wird.IMG_ARC_EDGED
In Verbindung mitIMG_ARC_NOFILL
werden der Start- und Endwinkel mit dem Mittelpunkt verbunden.
Die einzelnen Konstanten lassen sich mit einem bitweisen OR
verbinden.
imageFilledArc($image, 100, 100, 75, 75, 90, 180, $black, IMG_ARC_PIE OR IMG_ARC_NOFILL);
Hier wird ein Kreissektor mit dem Mittelpunkt (100,100) und einer Breite und Höhe von 75 Pixel gezeichnet. Der Startwinkel ist 90, der Endwinkel 180 und die Farbe $black
. Als Stil wurde festgelegt, dass das Kreisdiagramm einen Bogen aufweisen soll und nicht mit der Farbe gefüllt wird, sondern dass nur eine Außenlinie gezeichnet werden soll.
Das Script zum Zeichnen des Diagramms folgt nun in Listing 1.12.
<?php
/* Variablen vordefinieren */
$poll_file = $_GET['pollfile'];
$poll_title = '';
$poll_values = Array();
$poll_captions = Array();
$poll_sum = 0;
/* Daten laden */
$pf = fopen($poll_file,"r");
if($pf)
{
$poll_title = trim(fgets($pf));
$poll_captions[0] = trim(fgets($pf));
$poll_values[0] = trim(fgets($pf));
$poll_captions[1] = trim(fgets($pf));
$poll_values[1] = trim(fgets($pf));
$poll_captions[2] = trim(fgets($pf));
$poll_values[2] = trim(fgets($pf));
$poll_captions[3] = trim(fgets($pf));
$poll_values[3] = trim(fgets($pf));
fclose($pf);
}
/* Gesamtsumme bilden */
for($i=0; $i<count($poll_values); $i++)
{
$poll_sum += $poll_values[$i];
}
/* Grafik erzeugen */
$image = imageCreate(400,300);
$bg = imageColorAllocate($image,255,255,255);
$black = imageColorAllocate($image,0,0,0);
$poll_col[0] = imageColorAllocate($image,225,0,0);
$poll_col[1] = imageColorAllocate($image,0,225,0);
$poll_col[2] = imageColorAllocate($image,0,0,225);
$poll_col[3] = imageColorAllocate($image,128,128,128);
/* Start- und Endwinkel setzen */
$ang_start = 270;
$ang_end = 270;
/* Teilst�cke zeichnen */
for($i=0; $i<count($poll_values); $i++)
{
/* Winkel berechnen */
$ang_start = $ang_end;
$ang_part = $poll_values[$i] / $poll_sum * 360;
$ang_end = $ang_start + $ang_part;
/* Kreisbogen zeichnen */
imageFilledArc($image,125,175,225,225,$ang_start,$ang_end,$poll_col[$i],IMG_ARC_PIE);
}
/* Texte ausgeben */
imageString($image,3,10,20,$poll_title,$black);
$pos_sy = 100;
for($i=0; $i<count($poll_captions); $i++)
{
$perc = round($poll_values[$i] / $poll_sum * 100);
$output = $poll_captions[$i].' '.$perc.'%';
imageString($image,2,275,$pos_sy,$output,$poll_col[$i]);
$pos_sy += 20;
}
/* Grafik ausgeben */
header('Content-Type: image/png');
imagePng($image);
imageDestroy($image);
?>
Listing 1.12: PHP-Script, das ein Kreisdiagramm zeichnet
Auf den ersten Blick mag dieses Listing ein wenig kompliziert aussehen. Das trifft jedoch nur zum Teil zu. Sehen Sie sich das Script einmal genauer an, und Sie werden feststellen, dass viele Dinge auf den zweiten Blick schon verständlicher werden.
Gleich zu Beginn wird die Variable $poll_file
definiert. Der Wert, der ihr zugewiesen wird, ist der Wert, der in der URI übergeben wurde. Der Aufruf des Scripts sollte also folgendermaßen aussehen:
list1.12.php?pollfile=poll1.txt
Die restlichen Variablen, die danach definiert werden, werden mit Oder auch nicht, siehe $poll_values und $poll_captions.verschiedenen Startwerten initialisiert.
Im folgenden Abschnitt wird nun die in der URI übergebene Datei geöffnet und zeilenweise ausgelesen. Der Aufbau der Datei könnte bzw. müsste laut Listing 1.12 folgendermaßen aussehen:
Welches Betriebssystem verwenden Sie am häufigsten?
Windows
75
Linux
65
MacOS
55
Anderes
45
In der ersten Zeile steht die Frage. Anschließend folgen dann in je zwei Zeilen der Titel der Auswahlmöglichkeit und der Wert. Basierend auf diesem Schema wird die Datei dann auch eingelesen. Die einzelnen Zeilen werden mit der Funktion fgets
eingelesen und unterschiedlichen Variablen zugewiesen. Die Zeile 1 wird an die Variable $poll_title
übergeben. Die Zeilen 2, 4, 6 und 8 werden an das Array $poll_captions
übergeben und die Zeilen 3, 5, 7 und 9 an das Array $poll_values
. Da fgets
auch mögliche Whitespace-Zeichen (also Zeilenvorschübe und ‑umbrüche) zurückgibt, werden diese mit der Funktion trim
herausgefiltert.
In einer for
-Schleife werden nun alle Werte des Arrays $poll_values
addiert und der Variablen $poll_sum
zugewiesen, da die Summe der Werte später für die Berechnung der Kreissektoren und Prozentwerte benötigt wird.
Im nächsten Schritt wird dann die Grafik mit 400 Pixel Breite und 300 Pixel Höhe erzeugt, und es werden sechs Farben definiert. $bg
wird als Hintergrundfarbe und $black
zur Ausgabe der Überschrift verwendet. Die anderen vier Farben werden dem Array $poll_col
zugewiesen und für die Kreissektoren genutzt.
Anschließend werden der Start- und der Endwinkel definiert. Als Wert wurde für beide 270 angegeben. Dies bedeutet, dass das erste Teilstück oben beginnt und das letzte oben endet.
In der nun folgenden Schleife werden die einzelnen Kreissektoren gezeichnet. Dabei arbeitet die Schleife alle Elemente des Arrays $poll_values
einzeln ab. Zu Beginn jedes Durchlaufs wird der Startwinkel auf den letzten Endwinkel gesetzt, damit die einzelnen Kreissektoren auch aneinander hängen. Dann wird in $ang_part
der Winkel des aktuellen Kreissektors berechnet. Diese Berechnung erfolgt durch einen einfachen Dreisatz, da die Summe der Werte dem Winkel 360 und der aktuelle Wert dem Winkel x
entspricht.
summe = 360
aktueller wert = x
Daraus ergibt sich folgende Formel (in Programmierschreibweise):
x = summe / aktueller wert × 360.
Der neue Endwinkel entspricht dann dem Startwinkel + x (bzw. $ang_part
).
Nun muss mit imageFilledArc
lediglich der Kreissektor gezeichnet werden. Als Mittelpunkt des Kreises wurde der Punkt (125,175) gewählt, und der Durchmesser des Kreises wurde auf 225 Pixel festgelegt (einzeln als Breite und Höhe angegeben). Damit auch ein vernünftiger Kreissektor gezeichnet wird, wird als Stil IMG_ARC_PIE
verwendet.
Im nächsten Schritt werden die Textausgaben erzeugt. Dabei werden sowohl der Titel der Umfrage als auch die Bezeichnungen der einzelnen Kreissektoren mit den dazugehörigen Prozentwerten in den entsprechenden Farben ausgegeben. Die Prozentwerte werden mit der gleichen Formel wie die Winkel berechnet – nur dass die Summe der Werte 100 % entspricht.
Zum Schluss wird die Grafik an den Browser gesendet und der belegte Speicher wieder freigegeben. Im Browser könnte dies dann wie in Abbildung 1.14 gezeigt aussehen.
Abbildung 1.14: Ausgabe des Listing 1.12 im Browser
Das Script aus Listing 1.12 ist jedoch noch nicht ganz perfekt. So müsste z. B. bei der Berechnung der Winkel zuvor überprüft werden, ob die Gesamtsumme 0 ist, ansonsten quittiert PHP den Versuch mit der Fehlermeldung: Division durch 0. Auch die errechneten Prozentwerte müssen nicht immer 100 % ergeben. Dies kann um 1 % variieren, da die Rundung der Werte nicht unbedingt korrekt erfolgen muss.
# Zeichensalat
Das nun folgende Beispiel ist mehr eine Spielerei als ein wirkliches Anwendungsbeispiel, verdeutlicht aber die Funktionsweise von imageColorAt
und imageColorsForIndex
. Die Funktion imageColorAt
ermittelt den Farbindex eines Pixels innerhalb einer Grafik.
int imageColorAt(int image, int x, int y)
Als erster Parameter muss der Zeiger auf die Grafik übergeben werden und als Parameter x und y die Koordinaten des Pixels, dessen Farbwert ermittelt werden soll. Die Funktion gibt dann den entsprechenden Index zurück.
Diesen Index können Sie an die Funktion imageColorsForIndex
übergeben und erhalten dann die entsprechenden Farbwerte.
array imageColorsForIndex(int image, int color_index)
Die Funktion gibt ein assoziatives Array mit den Farbanteilen Rot, Grün und Blau zurück. Die Schlüssel der einzelnen Elemente lauten red
für Rot, green
für Grün und blue
für Blau.
Das folgende Listing verwendet diese beiden Funktionen, um ein Bild als Zeichensalat auszugeben.
<?php
/* Variablen definieren */
$img_file = $_GET['imgfile'];
$colormode = $_GET['colmode'];
$img_w = 0;
$img_h = 0;
/* Dateityp ermitteln und öffnen */
$pos = strrpos($img_file,'.') + 1;
$file_ext = substr($img_file,$pos);
switch(strToLower($file_ext))
{
case 'png' :
$image = imageCreateFromPng($img_file);
break;
case 'jpg':
case 'jpeg':
$image = imageCreateFromJPEG($img_file);
break;
}
/* Grafikabmessungen ermitteln */
$img_w = imagesx($image);
$img_h = imagesy($image);
/* Zeichenausgabe im Browser */
echo "<html><head><title>$img_file als Zeichensalat</title></head>";
echo '<body style="background-color:#000000"><pre style="font-size:4px;">';
for($i=0; $i<$img_h; $i+=2)
{
for($j=0; $j<$img_w; $j++)
{
$color = imageColorAt($image,$j,$i);
$rgb = imageColorsForIndex($image,$color);
switch($colormode)
{
case 'normal':
printf('<font color="#%02x%02x%02x">@</font>',$rgb['red'],$rgb['green'],$rgb['blue']);
break;
case 'reverted':
printf('<font color="#%02x%02x%02x">@</font>',$rgb['blue'],$rgb['green'],$rgb['red']);
break;
case 'inverted':
printf('<font color="#%02x%02x%02x">@</font>',255-$rgb['red'],255-$rgb['green'],255-$rgb['blue']);
break;
default:
printf('<font color="#%02x%02x%02x">@</font>',$rgb['red'],$rgb['green'],$rgb['blue']);
break;
}
}
echo "\n";
}
imageDestroy($image);
echo '</pre></body></html>';
?>
Listing 1.13: PHP-Script, das eine Grafik als Zeichensalat ausgibt
Das Script erwartet beim Aufruf zwei Parameter: imgfile
und colmode
. Diese beiden werden zu Beginn des Scripts den beiden Variablen $img_file
und $colormode
zugewiesen. Anschließend wird der Typ der angegebenen Grafik anhand der Dateiendung ermittelt und mit der entsprechenden Funktion geöffnet (dies kennen Sie bereits aus Abschnitt 1.6, Thumbnails erzeugen).
Im nächsten Schritt werden die Abmessungen der Grafik festgestellt und in den Variablen $img_w
und $img_h
gespeichert.
Nun folgt die eigentliche Ausgabe der Grafik im Browser. Zuerst wird ein normaler Beginn eines HTML-Dokuments ausgegeben, der mit dem Start-Tag eines pre
-Elements endet. Nun folgen zwei ineinander verschachtelte for
-Schleifen. Die erste Schleife wird durchlaufen, solange $i
kleiner als $img_h
ist. Die Inkrementierung erfolgt dabei in zwei Schritten. Die zweite, innere Schleife wird durchlaufen, solange $j
kleiner als $img_w
ist.
Innerhalb der Schleifen ermittelt die Funktion imageColorAt
den Palettenindex der Farbe des Pixels an Position ($j
,$i
). In der nächsten Zeile ermittelt dann imageColorsForIndex
die einzelnen Farbanteile des Palettenindex. In der switch
-Anweisung wird überprüft, ob $colormode
den Wert normal
, reverted
oder inverted
besitzt. Je nachdem, welcher Modus gesetzt wurde, wird ein anderer Anweisungsblock der switch
-Anweisung ausgeführt. Alle geben jedoch ein font
-Element im Browser aus, das als Wert für das color
-Attribut die drei ermittelten Farbanteile und ein @
-Zeichen im Gültigkeitsbereich erhält.
normal
Die Farben werden ganz normal in hexadezimaler Formatierung in der Reihenfolge RRGGBB ausgegeben.reverted
Die Farben werden in hexadezimaler Formatierung, aber in der Reihenfolge BBGGRR ausgegeben.inverted
Die Farbwerte werden von 255 abgezogen und in der Reihenfolge RRGGBB in hexadezimaler Formatierung ausgegeben.
Wurde kein Modus für die Farbe gesetzt, wird der Modus normal
verwendet. Wie das Ganze im Modus reverted
im Browser aussieht, sehen Sie in Abbildung 1.15.
Sollten Sie sich nun fragen, warum ich das Ganze als Zeichensalat bezeichne, sollten Sie sich einfach den Quelltext des ausgegebenen HTML-Dokuments ansehen. Sie werden dann verstehen, was ich meine. Bei der Ausgabe der Grafik phpbig.png umfasst das HTML-Dokument exakt 495.148 Zeichen, was in etwa 483 kB sind. Einen wirklich sinnvollen Einsatz gibt es für dieses Script also nicht, es ist jedoch eine recht nette Spielerei.
Im Internet finden Sie unter der Adresse http://www.sebastian-r.de/asciiart/ ein weiteres Beispiel. Abhängig von den einzelnen Farbwerten werden dort zusätzlich noch unterschiedliche Zeichen verwendet.
Abbildung 1.15: Ausgabe des Listing 1.13 durch den Aufruf von list1.13.php?imgfile=phpbig.png&colmode=reverted
# Zusammenfassung
- Die GD-Library stellt in PHP verschiedene Funktionen zur Grafikmanipulation zur Verfügung.
- Eine neue Grafik wird mit der Funktion
imageCreate
oderimageCreateTrueColor
erzeugt. - Eine vorhandene Grafik kann mit
imageCreateFromPng
oderimageCreateFromJPEG
geöffnet werden. - Zeichenketten können mit der Funktion
imageString
ausgegeben werden. - Farben werden durch
imageColorAllocate
oderimageColorResolveAlpha
definiert. - Formen wie Linien, Rechtecke, Kreise oder Kreisbögen werden mit den Funktionen
imageLine
,imageDashedLine
,imageRectangle
,imageFilledRectangle
,imageEllipse
,imageFilledEllipse
,imageArc
undimageFilledArc
in die Grafik gezeichnet. - Mit der Funktion
imagePng
oderimageJPEG
wird eine erzeugte Grafik an den Browser gesendet, und mitimageDestroy
wird der belegte Speicher einer Grafik wieder freigegeben.
# Fragen und Übungen
- Welchen Unterschied weisen Grafiken auf, die mit
imageCreate
oderimageCreateTrueColor
erzeugt wurden? - Welche Funktion müssen Sie verwenden, um eine (teil)transparente Farbe zu definieren? Welche Voraussetzungen müssen erfüllt sein?
- Was bewirkt die Funktion
imageCopyResized
? - Finden Sie eine Möglichkeit, wie aus einem Farbbild, ohne eine GD-Funktion zu verwenden, ein Graustufenbild werden kann.
- Versuchen Sie Ihre Idee der Farbe-Graufstufen-Umwandlung umzusetzen, indem Sie ein Script schreiben, das eine Grafik öffnet und in Graustufen umgewandelt im Browser ausgibt.