Wykorzystanie biblioteki GD do generowania grafiki

Transkrypt

Wykorzystanie biblioteki GD do generowania grafiki
Artykuł pochodzi z czasopisma PHP Solutions.
Do ściągnięcia bezpłatnie ze strony:
www.phpsolmag.org
Bezpłatne kopiowanie i rozpowszechanie artykułu dozwolone
pod warunkiem zachowania jego obecnej formy i treści.
Marcin Makarewicz
Wykorzystanie biblioteki GD do generowania grafiki
Automatyczne przygotowywanie
grafik w alternatywnych rozmiarach
czy dynamiczne generowanie wykresów to tylko niektóre z możliwości,
jakie kryje w sobie biblioteka GD.
G
Listingi zostały zamieszczone na płycie CD.
• http://www.php.net/gd
58
enerowanie grafiki na stronach
WWW daje wiele korzyści.
Wszelkiego rodzaju wykresy
umożliwiają o wiele lepszą interpretację
przedstawionych danych niż np. tabele.
Możliwości takiej prezentacji danych
w formie graficznej oferuje między
innymi biblioteka GD.
Dzięki niej bez trudu możemy wygenerować wykres lub narysować figurę
czy bryłę. Jeśli chcemy na naszych stronach umieszczać dynamicznie generowane rysunki, np. miniatury obrazków
z możliwością wyboru ich rozmiarów
czy statystki odwiedzin, to najlepiej i najprościej skorzystać właśnie z GD.
Niestety trudno znaleźć w sieci,
nie wspominając już o książkach, dobre
opracowania, które przybliżałyby tę
tematykę. Mamy nadzieje, że ten artykuł to ułatwi.
Konfiguracja PHP i GD
W systemie Windows musimy zadbać
o to, żeby plik z biblioteką php_gd.dll
www.phpsolmag.org
znajdował się w katalogu, gdzie PHP
trzyma swoje rozszerzenia, czyli w katalogu extensions, który generalnie umiejscowiony jest tam, gdzie zainstalowane zostało PHP. Następnie dokonujemy odpowiedniego wpisu w pliku php.ini:
extension=php _ gd.dll.(od wersji PHP
4.3.2 bibliotekę GD zastąpiła GD2 – plik
php_gd2.dll). W systemie Linux najlepiej
Co należy wiedzieć?
Czytelnik powinien posiadać podstawową znajomości PHP, w tym
również obiektowych cech tego
języka.
Co obiecujemy?
Z artykułu dowiesz się jak dokonywać operacji na obrazkach (rysowanie, zmiana wielkości) oraz w jaki
sposób generować wykresy słupkowe.
PHP Solutions 3/2004
Listing 1. Osadzenie dynamicznie
generowanego obrazka w kodzie
HTML
<HTML>
<BODY>
<IMG SRC="image.php?
caption=Caption"
width="400" height="300"
border="0">
</BODY>
</HTML>
wybrać pakiet GD podczas instalacji systemu. Jeśli kompilujemy PHP ręcznie, to
podczas konfiguracji należy dodać:
./configure --with-gd
(oprócz -- with-gd występują tu jeszcze
inne, opcjonalne składniki, w zależności
od wybranych przez nas opcji).
Następnie kompilujemy PHP poleceniami make oraz make install.
Na czym polega
dynamiczne
generowanie grafiki?
Być może nie każdy wie, ale tak jak
strona HTML może być dynamicznie
generowana przez PHP, tak samo może
być generowany każdy inny plik dowolnego formatu. Zamiast określać w kodzie HTML znaczniki odpowiadające
obrazkom ze ścieżkami do plików graficznych na serwerze – równie dobrze
możemy umieścić zastępczo ścieżkę
do skryptu PHP, który wygeneruje dane
odpowiadające obrazkowi konkretnego
formatu. Przeglądarce nie zrobi to większej różnicy.
Tak więc obrazki będą generowane dynamicznie przez skrypt PHP, a wyświetlać je będzie przeglądarka internetowa. Jeśli obrazki mamy zamiar umieścić na stronie HTML (która może być
oczywiście wygenerowana przez PHP),
element IMG będzie posiadał przypisaną
atrybutowi SRC ścieżkę do skryptu generującego grafikę. W ścieżce możemy
PHP Solutions 3/2004
Listing 2. Napis i rysunek na obrazku stworzone za pomocą GD – plik
image.php
<?php
//odczytujemy obrazek z pliku jpg
$image = imagecreatefromjpeg('images/civic_full.jpg');
//alokujemy kolory które wykorzystamy dalej
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);
$red = ImageColorAllocate($image, 255, 0, 0);
//określamy treść napisu na obrazku
$caption = $_GET['caption']?$_GET['caption']:"civic";
//odczytujemy rozmiary obrazka
$width = imagesx($image); $height = imagesy($image);
//rysujemy na całej szerokości poziomą linię
imageline($image, 0, $height/2, $width, $height/2, $red);
$count = 10;
//pętla odpowiedzialna za rysowanie czworokątów
for($i=1; $i<$count; $i++) {
//tablica współrzędnych wierzchołków (x0, y0, x1, y1, ...)
$points = Array($width*(1-$i/$count)/2, $height*(1-$i/$count)/2,
$width*(1-$i/$count)/2, $height*(1+$i/$count)/2,
$width*(1+$i/$count)/2, $height*(1+$i/$count)/2,
$width*(1+$i/$count)/2, $height*(1-$i/$count)/2);
);
//rysujemy wielokąt na podstawie współrzędnych punktów w tablicy
imagepolygon($image, $points, sizeof($points)/2, $black);
}
//umieszczamy tekst w centralnej części obrazka
imagestring($image, 10, $width/2, $height/2, $caption, $white);
//definiujemy nagłówek, określając typ danych wyjściowych
header("Content-type: image/png");
//generujemy obrazek
imagepng($image);
//zwalniamy pamięć zajętą przez obrazek
imagedestroy($image);
?>
Rysunek 1. Zmodyfikowany obrazek – Listing 2
www.phpsolmag.org
59
Listing 3. Wczytanie obrazka źródłowego z odpowiednim skalowaniem – plik
thumb.php (1/2)
<?php
if($_GET['width'] > 0) {
$width = $_GET['width'];
} else
{
$width = 200;
}
if($_GET['height'] > 0) {
$height = $_GET['height'];
} else
{
$height = 200;
}
if($_GET['filename']) {
$filename = $_GET['filename'];
} else
{
$filename = 'civic.jpg';
}
Listing 4. Plik thumb.php (2/2)
...
//obrazek z pliku jpg
$src_image = imagecreatefromjpeg($filename);
$image = imagecreate($width, $height);
Techniki
//alokujemy kolory, które wykorzystamy dalej
$bg = imagecolorallocate($image, 200, 200, 200);
$white = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
$margin_x = 10;
$margin_y = 10;
$w = $width-2*$margin_x;
$h = $height-2*$margin_y;
$src_w = imagesx($src_image);
$src_h = imagesy($src_image);
...
//czy wyświetlamy w oryginalnych rozmiarach
if(($w > $src_w) && ($h > $src_h)) {
$dst_w = $src_w;
$dst_h = $src_h;
} else
//czy skalujemy względem wymiaru poziomego
if(($w/$h) < ($src_w/$src_h)) {
$dst_w = $w;
$dst_h = $w*$src_h/$src_w;
} else
Rysunek 2. Katalog obrazków
60
www.phpsolmag.org
?>
//czy skalujemy względem wymiaru
//pionowego
{
$dst_w = $h*$src_w/$src_h;
$dst_h = $h;
}
imagecopyresized($image,
$src_image,
($width-$dst_w)/2,
($height-$dst_h)/2,
0, 0, $dst_w,
$dst_h,
$src_w, $src_h);
//umieszczamy tekst na obrazku
imagestring($image, 0,$margin_x,
($height-$margin_y),
$filename, $white);
//odpowiedni nagłówek dla danych
//wyjściowych
header("Content-type:
image/jpeg");
//generujemy obrazek
imagejpeg($image);
//zwalniamy pamięć
imagedestroy($image);
oczywiście określić zmienne, od których może zależeć wyświetlany obrazek
– patrz Listing 1.
GD umożliwia tworzenie obrazka
o z góry zadanej rozdzielczości – funkcja imagecreate(), jak również pozwala
na wczytanie określonego formatu obrazka z pliku – odpowiednio (w zależności od
formatu pliku graficznego) funkcje imagecreatefromjpeg(), imagecreatefrompng()
itp. Obsługiwane formaty obrazków
zależą od wersji biblioteki GD oraz PHP.
Na początek przedstawimy kilka
podstawowych funkcji. Wczytamy obrazek z pliku, a następnie narysujemy
na nim pewne elementy graficzne. Wykorzystując funkcję do rysowania linii imageline(), umieścimy kreskę o wcześniej
ustalonej grubości imagesetthickness().
Dodatkowo na obrazku zamieścimy tekst
za pomocą funkcji imagestring(). Funkcji do pisania tekstów jest kilka, odpowiadają za wykorzystanie różnych formatów
czcionek.
Aby obrazek został poprawnie
wyświetlony określamy nagłówek odpowiednio do generowanego formatu
obrazka header("Content-type: image/
png"). W przypadku systemu Linux,
odpowiednie typy plików możemy znaleźć najczęściej w pliku /etc/mime.types.
Jeśli udało się nam napisać skrypt
bezbłędnie, obrazek powinien ukazać
PHP Solutions 3/2004
Generowanie grafiki
się w oknie przeglądarki po wpisaniu adresu URL skryptu. Ważne jest,
aby skrypt zwrócił przeglądarce tylko
to, co wygeneruje w naszym przypadku funkcja imagepng(). Warto zwrócić uwagę na to, żeby znaczniki <?php
oraz ?> były umieszczone odpowiednio
na samym początku skryptu i na jego
końcu, a poza nimi nie było żadnych
znaków (znaków końca linii czy spacji).
W przeciwnym razie przeglądarka otrzyma dodatkowe dane, przez co format
nie będzie poprawnie zinterpretowany.
Na Rysunku 1 widać efekt działania
skryptu, którego kod znajduje się na
Listingu 2.
Katalog obrazków
– miniatury
Na stronach WWW często spotyka się
miniatury obrazków. Przeważnie stanowią one łącze do analogicznego obrazu
w pełnej rozdzielczości. Zastosowanie
miniatur jako obrazków przeglądowych
ma wiele zalet. Jest nieodzownym elementem w przypadku katalogów obrazków czy galerii zdjęć. Wyszukanie konkretnego obrazka jest łatwiejsze, aniżeli
przeglądanie kolejno zdjęć w pełnej rozdzielczości, w szczególności dla użytkowników Internetu korzystających z łącza o małej przepustowości. W przypadku stron prezentujących informacje, metoda taka pozwala na estetyczne
wkomponowanie miniatur w treści serwisów, których czytelnicy mogą nie być
w ogóle zainteresowani zdjęciami.
Przygotowanie grafik w alternatywnych rozmiarach z wykorzystaniem programów graficznych może być bardzo
pracochłonne. Z wykorzystaniem biblioteki GD możemy to zrobić automatycznie. Zdjęcia mogą mieć oczywiście
różne proporcje i rozmiary.
Nasz przykład tworzy miniaturki obrazków o określonych rozmiarach,
zachowując przy tym proporcje obrazów
źródłowych. Przyjęte zostały przy tym
założenia:
•
•
skala obrazka określana jest tak,
aby cały był widoczny (nie był przycinany),
jeśli obrazek źródłowy jest mniejszy
od wybranych rozmiarów – nie jest
skalowany (powiększany).
Zacznijmy od wczytania obrazka źródłowego – Listing 3 (thumb.php). Funkcje imagesx(), imagesy() pozwalają
na odczytanie jego rozmiarów. Następ-
PHP Solutions 3/2004
Listing 5. Plik catalog.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE> Images </TITLE></HEAD><BODY>
<?php
//określamy nazwę skryptu generującego obrazki
$image = 'thumb.php';
//określamy szerokość obrazków na podstawie parametru width
if($_GET['width'] > 0) {
$width = $_GET['width'];
} else
{
$width = 200;
}
//określamy wysokość obrazków na podstawie parametru height
if($_GET['height'] > 0) {
$height = $_GET['height'];
} else
{
$height = 200;
}
//generujemy formularz wyboru rozmiarów grafik przeglądowych
echo '<FORM ACTION="'.$_SERVER['SCRIPT_NAME'].'" METHOD="GET">';
echo '<SELECT NAME="width">';
echo '<OPTION VALUE="">-- width --</OPTION>';
for($i=100; $i<700; $i+=100) {
echo '<OPTION VALUE="'.$i.'"';
if($i == $width) {
echo ' SELECTED';
}
echo '>'.$i.'</OPTION>';
}
echo '</SELECT>';
echo '<SELECT NAME="height">';
echo '<OPTION VALUE="">-- height --</OPTION>';
for($i=100; $i<700; $i+=100) {
echo '<OPTION VALUE="'.$i.'"';
if($i == $height) {
echo ' SELECTED';
}
echo '>'.$i.'</OPTION>';
}
echo '</SELECT>';
echo '<INPUT TY PE="SUBMIT" VALUE=" SHOW ">';
echo '</FORM>';
//definiujemy nazwę katalogu, w którym znajdują się obrazki
$path = 'images/';
$dir = opendir('images');
//czytamy zawartość katalogu
while ($file = readdir($dir)) {
//wybieramy tylko pliki z rozszerzeniem .jpg
if(is_file($path.$file) && preg_match("/\.jpg$/i", $file)) {
//generujemy link do oryginalnego obrazka
echo '<A HREF="'.$path.$file.'" TARGET="_blank">';
//osadzamy obrazek ze sciezką do skryptu generującego
//grafiki przeglądowe
echo '<IMG SRC="'.$image.'?filename='.$path.$file.'
&width='.$width.'&height='.$height.'"
WIDTH="'.$width.'" HEIGHT="'.$height.'"
BORDER="1" HSPACE="8" VSPACE="8">';
echo '</A>';
}
}
//zamykamy deskryptor
closedir($dir);
?></BODY></HTML>
www.phpsolmag.org
61
Listing 6. Plik Chart.class.php (1/2)
<?php
Techniki
class Chart {
var $image; //identyfikator obrazka
var $title = 'Chart'; //tytuł wykresu
var $width = 800; //szerokość obrazka wynikowego
var $height = 600; //wysokość obrazka wynikowego
var $margin_x = 40; //margines poziomy
var $margin_y = 40; //margines pionowy
var $bar_w = 0.8; //stosunek szerokości kolumn do odległości między nimi
var $bar_color = Array(100, 160, 200); //kolor kolumn
var $text_color = Array(0, 0, 0); //kolor tekstu
var $grid_color = Array(240, 240, 200); //kolor siatki
var $_x_min; //minimalna wartość x przestrzeni wykresu
var $_x_max; //maksymalna wartość x przestrzeni wykresu
var $_y_min; //minimalna wartość y przestrzeni wykresu
var $_y_max; //maksymalna wartość y przestrzeni wykresu
var $_range_w; //szerokość przestrzeni wykresu
var $_range_h; //wysokość przestrzeni wykresu
//Metoda draw - generuje obrazek
//jako argument przekazujemy tablice wartosci
function draw($series) {
//tworzymy obrazek o zadanej szerokości i wysokości
$this->image = imagecreate($this->width, $this->height);
//alokacja koloru, który stanie się kolorem tła
$this->translateColor();
//wyznaczamy przestrzeń wykresu
$this->calcRange($series);
//rysujemy siatkę
$this->drawGrid();
//nanosimy kolejne wartości na wykres
foreach($series as $x=>$y) {
$this->setValue($x, $y);
}
//umieszczamy tytuł wykresu
imagestring($this->image, 5, $this->margin_x/2,
$this->margin_y/2, $this->title,
$this->translateColor($this->text_color));
header("Content-type: image/png");
imagepng($this->image);
imagedestroy($this->image);
exit;
}
//Metoda drawGrid - rysuje siatkę na obrazku
//argumentem może być odległość pomiędzy
//kolejnymi liniami
function drawGrid($size = 20) {
$y = $size*round($this->_y_min/$size) - $size;
while($y < ($this->_y_max + $size)) {
// wyliczamy kolejne wartości y
$y0 = $this->translateCoordY($y);
// rysujemy poziome linie
imageline($this->image, 0, $y0, $this->width, $y0,
$this->translateColor($this->grid_color));
$y += $size;
}
}
//Metoda setValue - rysuje prostokąt na podstawie
//zadanych wartości
//argumenty to wartości x i y
function setValue($x, $y) {
...
62
nie tworzymy nowy obrazek, którego rozmiary będą odpowiadać grafice wynikowej. Na podstawie rozmiarów obrazka źródłowego decydujemy,
czy obrazek będzie skalowany, a jeśli
tak to względem którego wymiaru. Nie
skalujemy obrazka w sytuacji, kiedy
jego szerokość i wysokość są mniejsze niż rozmiary pola, w jakim zostanie
umieszczony. W przeciwnym razie przy
powiększeniu powstałby nieprzyjemny efekt wielkich pikseli. W przypadku galerii zdjęć, możemy wykorzystać
nasze umiejętności nie tylko do tworzenia grafik przeglądowych, ale również do prostych modyfikacji obrazków. Możemy stworzyć swego rodzaju szablon, według którego każdy obrazek w naszym serwisie będzie posiadał charakterystyczną ramkę lub zostanie oznaczony naszym logo. Ale to już
zostawiamy do eksperymentów czytelników.
Efekt widoczny na Rysunku 2
jest wynikiem działania skryptów
thumb.php oraz catalog.php. Skrypt
catalog.php (patrz Listing 5) generuje
HTML z formularzem do wyboru rozmiarów miniatur oraz obrazki przeglądowe.
Generowanie wykresów
Generalnie najczęściej przyjętymi formami zestawiania danych są tabele
oraz wykresy. Zestawienie danych
na wykresie pozwala na ich niewątpliwie
łatwiejszą interpretację. Trudno wyobrazić sobie lepszy sposób na wizualizację dużej ilości danych i różnego rodzaju zależności (np. kształtowania się
kursów walut) niż dynamicznie generowane wykresy. W naszym przykładzie
zajmiemy się tworzeniem wykresu słupkowego.
Na Listingu 6 przedstawiona została
klasa, umożliwiająca tworzenie wykresu na podstawie danych umieszczonych
w tablicy. Po tym pokażemy jak można
ją rozszerzyć, aby wykresy miały bardziej atrakcyjną formę.
Tworzenie klasy Chart zaczniemy
do zdefiniowania właściwości:
•
•
•
•
width, height
_ x _ min, _ x _ max, _ y _ min,
_ y _ max
•
www.phpsolmag.org
– identyfikator obrazka,
– rozmiary wynikowej
grafiki,
margin _ x, margin _ y – marginesy,
image
wykresu,
– ograniczenia przestrzeni
– szerokość
i wysokość przestrzeni wykresu.
_ range _ w, _ range _ h
PHP Solutions 3/2004
Generowanie grafiki
Podstawową metodą będzie draw(),
której wywołanie pozwoli wygenerować grafikę. Argumentem jej wywołania
będzie tablica zawierająca serię danych
do prezentacji. Aby odpowiednio rozmieścić wartości na wykresie, stworzymy metodę wyznaczającą ich zakres
calcRange() oraz metody, które pozwolą rzutować punkty przestrzeni wykresu na określony obszar obrazka wynikowego translateCoordX() i translateCoordY(). Zabiegi te zagwarantują prezentację serii danych w stosownym miejscu,
bez potrzeby uprzedniego ich dostosowywania.
Metoda setValue() posłuży do naniesienia konkretnej wartości na wykres
przez narysowanie słupka o określonej wysokości. Do wyboru koloru wykorzystamy metodę translateColor(), która będzie odpowiedzialna za jego alokację.
Na Listingu 8 (chart.php) został
przedstawiony przykład wykorzystania
klasy Chart., a efekt zobrazowany jest
Rysunku 3. W przykładzie utworzony
został obiekt Chart, następnie wypełniono tablicę danych losowymi wartościami
z przedziału (-200, 200). Wykres został
narysowany przez wywołanie metody
draw().
Możemy również w bardziej efektowny sposób wykorzystać naszą klasę
Chart i narysować podobny, ale bardziej
zaawansowany wykres – patrz Listing 9.
Efekt działania skryptu chart2.php widzimy na Rysunku 4.
W pliku chart2.php dodatkowo rozszerzymy klasę Chart przeciążając
przy tym metody setValue() i translateColor(). W tym wypadku dla lepszych efektów wizualizacji posłużymy się cieniami i odpowiednio rozjaśnionymi kolorami. Słupki narysujemy
z obwódkami, aby były bardziej rozróżnialne.
Listing 7. Plik Chart.class.php (2/2)
...
//określamy wszystkie współrzędne prostokąta o szerokości bar_w
$p = Array(
($x-$this->bar_w/2), $y,
($x+$this->bar_w/2), $y,
($x+$this->bar_w/2), 0,
($x-$this->bar_w/2), 0
);
//przekształcamy je na współrzędne obrazka
$r = $this->translatePoly($p);
//rysujemy prostokąt
imagefilledpolygon($this->image, $r, sizeof($r)/2,
$this->translateColor($this->bar_color));
Metody klasy Chart
Metoda draw(). Jak już wcześniej wspomniano, argumentem wywołania tej
metody jest seria danych – tablica wartości. Na początku tworzymy obrazek
o szerokości width i wysokości height.
Wybieramy kolor, który będzie kolorem tła
obrazka – translateColor(), przy czym
bez podania argumentu otrzymujemy
kolor biały. Następnie wyznaczona jest
przestrzeń wykresu – metoda calcRange(). Siatka zostaje naniesiona przez wywołanie metody drawGrid(). Słupki
odpowiadające wartościom są rysowane przez wywołanie metody setVa-
PHP Solutions 3/2004
?>
}
}
//Metoda calcRange - wyznacza przestrzeń wykresu
//argumentem jest tablica wartości
function calcRange($series) {
//zaczynamy od początku układu współrzędnych
$this->_x_min = 0; $this->_y_min = 0;
$this->_x_max = 1; $this->_y_max = 1;
foreach($series as $x=>$y) {
//zmieniamy zakres w zależności od wartości
if($x >= $this->_x_max) $this->_x_max = $x;
if($x < $this->_x_min) $this->_x_min = $x;
if($y >= $this->_y_max) $this->_y_max = $y;
if($y < $this->_y_min) $this->_y_min = $y;
}
//określamy szerokość i wysokość wykresu
$this->_range_w = $this->_x_max-$this->_x_min;
$this->_range_h = $this->_y_max-$this->_y_min;
}
//Metoda translatePoly - rzutuje punkty przestrzeni
//wykresu na obszar obrazka,
//argumentem jest tablica kolejnych punktów x, y
function translatePoly($p) {
$r = Array();
for($i=0; $i<sizeof($p); $i+=2) {
//przekształcamy kolejno punkty
$r[] = $this->translateCoordX($p[$i]);
$r[] = $this->translateCoordY($p[$i+1]);
}
return $r;
}
//Metody translateCoordX i translateCoordY – przekształcają
//odpowiednio współrzędne wykresu
//argumentem jest wartość odpowiednio x i y
//metoda zwraca wartość współrzędnej dla obszaru obrazka
function translateCoordX($x) {
return round($this->margin_x+($this->width-2*
$this->margin_x)*($x-$this->_x_min)/
$this->_range_w);
}
function translateCoordY($y) {
return round($this->margin_y-($this->height-2*
$this->margin_y)*($y-$this->_y_max)/
$this->_range_h);
}
//Metoda translateColor - pozwala uzyskać identyfikator
//koloru, argumentem jest tablica składowych odpowiednio
//RGB, metoda zwraca identyfikator koloru
function translateColor($rgb = Array(255, 255, 255)) {
return imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]);
}
www.phpsolmag.org
63
Listing 8. Plik chart.php
<?php
require('Chart.class.php');
//liczba wartości
$count = 32;
//obiekt Chart
$chart = new Chart();
//tworzymy tablice kolejnych
//wartości losowych
$array = Array();
for($i=0; $i<$count; $i++) {
$array[] = rand(-200, 200);
}
//nanosimy wartości
//i generujemy obraz
$chart->draw($array);
?>
Rysunek 3. Efekt działania skryptu chart.php
w pętli, przy czym argumentami są
odpowiednio klucz i wartość elementów
tablicy danych. Dalej umieszczany jest
tytuł wykresu w określonym kolorze. Na
koniec wysyłany jest nagłówek i wygenerowany zostaje obrazek do wyświetlenia.
Przed zakończeniem skryptu zwalniany
jest obszar pamięci zajmowany przez obrazek.
Metoda calcRange(). Niniejsza
metoda pozwala wyznaczyć zakres
danych. Jako, że przestrzeń wykresu nie może być pusta – zaczynamy
od przyjęcia, że pole ma rozmiary 1
na 1. W pętli analizujemy kolejne warto-
ści i odpowiednio rozszerzamy tę przestrzeń. Po wyznaczeniu minimalnych
i maksymalnych wartości określamy
szerokość i wysokość tej przestrzeni.
Metody translateCoordX() i translateCoordY(). Metody te służą do określenia współrzędnych piksela na obrazku
dla określonego elementu tablicy danych,
czyli dla odpowiedniego klucza i wartości
otrzymujemy współrzędną x i y punktu.
Jest to pewnego rodzaju odwzorowanie,
dzięki któremu możemy rzutować punkty
z przestrzeni wykresu na ograniczony
obszar obrazka. Uwzględniamy przy tym
przypisane obrazkowi marginesy.
Techniki
lue()
Rysunek 4. Efekt działania skryptu chart2.php
64
www.phpsolmag.org
Metoda translatePoly(). Jest to
pomocnicza metoda, która ułatwia
rzutowanie na obszar obrazka wielu
kolejnych punktów. Wartości x i y
pierwszego punktu są pierwszym
i drugim elementem w tablicy, trzecim i czwartym elementem są współrzędne kolejnego punktu itd. Metoda
została wprowadzona z myślą o rysowaniu wieloboków (imagepolygon()
i imagefilledpolygon()), gdzie jest
identyczna konwencja zapisu współrzędnych punktów.
Metoda translateColor(). Argumentem wywołania metody jest tablica trzech elementów – składowych R
(czerwony), G (zielony), B (niebieski)
koloru. Zwracany jest identyfikator odpowiadającego koloru.
Metoda drawGrid(). Opcjonalnym
argumentem wywołania tej metody jest
wartość, co którą ma być umieszczona pozioma linia. Linie są nanoszone
w pętli w ten sposób, aby pierwsza znajdowała się poniżej najmniejszej wartości słupka, a ostatnia powyżej poziomu
słupka o największej wartości. Oczywiście pomiędzy nimi musi się znaleźć
linia odpowiadająca poziomej osi wykresu. Linie rozciągają się na całą szerokość obrazka.
Metoda setValue(). Jest to metoda
odpowiedzialna za rysowanie słupków odpowiadających kolejnym wartościom wykresu. Słupek jest prostokątem o szerokości zdefiniowanej
przez właściwość bar _ w. Pozycja x
i poziom y jest zależny od klucza i wartości elementu w tablicy zawierają-
PHP Solutions 3/2004
Generowanie grafiki
Listing 9. Plik chart2.php (1/2)
Listing 10. Plik chart2.php (2/2)
<?php
...
require('Chart.class.php');
class CChart extends Chart {
var $shadow_color = Array(0, 0, 0); // kolor cienia
var $shadow_size = 2; //przesunięcie cienia
//Metoda setValue - rysuje prostokąt na podstawie
//zadanych wartości, argumenty to wartości x i y
function setValue($x, $y) {
//określamy wszystkie współrzędne prostokąta
$x0 = $this->translateCoordX($x-$this->bar_w/2);
$y0 = $this->translateCoordY($y);
$x1 = $this->translateCoordX($x+$this->bar_w/2);
$y1 = $this->translateCoordY(0);
//przesuwamy współrzędne dla uzyskania efektu cienia
$r = Array(
$x0+$this->shadow_size, $y0+$this->shadow_size,
$x0+$this->shadow_size, $y1,
$x1+$this->shadow_size, $y1,
$x1+$this->shadow_size, $y0+$this->shadow_size
);
//rysujemy cień
imagefilledpolygon($this->image, $r, sizeof($r)/2,
$this->translateColor($this->shadow_color));
//określamy kolor o jasności zależnej od wartości
//i barwie zależnej od położenia względem osi
if($y < 0) {
$bar_color_id = $this->translateColor
(Array(170, 255, 0), 1-$y/$this->_y_min);
} else
{
$bar_color_id = $this->translateColor
(Array(0, 135, 200), 1-$y/$this->_y_max);
}
$r = Array($x0, $y0, $x0, $y1, $x1, $y1, $x1, $y0);
//rysujemy wypełniony prostokąt
imagefilledpolygon($this->image, $r, sizeof($r)/2,
$bar_color_id);
//rysujemy ramkę na prostokącie
imagepolygon($this->image, $r, sizeof($r)/2,
$this->translateColor($this->shadow_color));
...
}
//opisujemy wartość uwzględniając położenie
if($y < 0) {
imagestring($this->image, 0, $x0, $y0+4, $y,
$this->translateColor($this->text_color));
} else
{
imagestring($this->image, 0, $x0, $y0-10, $y,
$this->translateColor($this->text_color));
}
cej serię danych. Zdefiniowane współrzędne są rzutowane na obszar obrazka, po czym naniesiony zostaje wielokąt – co w naszym przypadku odpowiada prostokątowi.
PHP Solutions 3/2004
Rozszerzenie klasy Chart
– CChart
Klasa CChart jest rozszerzeniem klasy
Chart polegającym na zmianie sposobu nanoszenia słupków, dodającym
www.phpsolmag.org
//Metoda translateColor //pozwala uzyskać identyfikator
//koloru odpowiednio
//rozjaśnionego
//argumentem jest tablica
//składowych RGB koloru i
//stopień rozjaśnienia koloru
//metoda zwraca identyfikator
//koloru
function translateColor($rgb =
Array(255, 255, 255), $p=0) {
if($p>255) {
$p = 255;
} else
if($p<0) {
$p = 0;
}
//wyliczamy wartości
//poszczególnych składowych
//koloru
$r = round($rgb[0]+
(255-$rgb[0])*$p);
$g = round($rgb[1]+
(255-$rgb[1])*$p);
$b = round($rgb[2]+
(255-$rgb[2])*$p);
return imagecolorallocate
($this->image, $r, $g, $b);
}
}
?>
//liczba wartości
$count = 32;
//obiekt Chart
$chart = new CChart();
//tworzymy tablice kolejnych
//wartości losowych
$array = Array();
for($i=0; $i<$count; $i++) {
$array[] = rand(-200, 200);
}
//nanosimy wartości i generujemy
//obraz
$chart->draw($array);
przy tym zmianę odcienia koloru w zależności od odpowiadającej mu wartości. Zostały tutaj przeciążone metody
setValue() i translateColor(). Dodane
zostały również dwie nowe właściwości
– shadow _ color oraz shadow _ size.
Metoda translateColor(). Metoda jest zmodyfikowana w stosunku do jej pierwotnej wersji. Różnica
polega na wprowadzeniu wagi, będącej drugim argumentem wywołania
metody. Waga określa stopień rozjaśnienia koloru, przy czym wartość
1 da nam kolor biały, zaś wartość 0
nie wpłynie na kolor.
65
wego prostokąta, uwzględniając przy
tym odpowiadającą słupkowi wartość. W zależności od tego czy wartość jest dodatnia czy ujemna – wybieramy jeden z dwóch kolorów, po czym
rozjaśniamy go – mniej dla wartości większych, bardziej dla wartości
mniejszych. Do tego rysujemy jeszcze ramkę wyróżniającą krawędzie.
Na koniec umieszczamy stosownie
nad lub pod słupkiem wartość w postaci liczbowej.
Podsumowanie
Rysunek 5. Rzutowanie punktów przestrzeni na obszar obrazka
Metoda setValue(). Na początku wyznaczamy współrzędne punktów odpowiadających wierzchołkom
66
słupka. Odpowiednio je modyfikując
rysujemy prostokąt dający efekt cienia.
Następnie wyznaczamy kolor właści-
www.phpsolmag.org
Opisane przykłady generowania
grafiki pokazują jak efektownie można
zaprezentować dane, czy przeprowadzać modyfikacje na gotowych
obrazkach.
Artykuł nie zamyka tematu i mamy
nadzieję, że zaciekawił czytelników
na tyle, aby część z nich pokusiła się
o eksperymentowanie we własnym
zakresie. Wykorzystanie GD nie jest
trudne, a daje ogromne możliwości uzyskania ciekawych efektów na własnej
stronie WWW. 
PHP Solutions 3/2004

Podobne dokumenty