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