9. Dynamiczne generowanie grafiki, cz. 3 9.1. Kopiowanie fragmentów obrazu Funkcja imagecopy służy do kopiowania fragmentów obrazka między dwoma różnymi obrazkami, lub w obrębie jednego. Uwaga, przy kopiowaniu w obrębie jednego obrazka należy unikać sytuacji, gdy obszary źródłowy i docelowy nakładają się. imagecopy(cel, źródło, x_celu, y_celu, x_źródła, y_źródła, wys, szer); y_źródła x_źródła y_celu x_celu wys cel szer źródło
9.2. Kopiowanie fragmentów obrazu z przenikaniem Funkcja imagecopymerge ma działanie zbliżone do poprzedniej, ale pozwala na nałożenie rgagmentu obrazu na obraz docelowy z płynnie regulowanym poziomem przezroczystości. Parametr ten przyjmuje wartości od 0 (nakładany fragment niewidoczny) do 100 (działanie takie jak imagecopy). imagecopymerge (cel, źródło, x_celu, y_celu, x_źródła, y_źródła, wys, szer, prz); przezroczystość 60% źródło cel przezroczystość 40%
9.3. Kopiowanie fragmentów obrazu ze skalowaniem Do przeskalowania prostokątnego obszaru obrazu można użyć jednej z dwóch funkcji: imagecopyresized lub imagecopyresampled. Funkcje te różnią się wyłącznie używanym algorytmem skalowania. Pierwsza z nich używa prostszego, ale szybszego algorytmu, druga wykonuje zmianę przestrzennej częstotliwości próbek obrazka z filtracją, co jest czasochłonne, ale o wiele lepiej wygląda. imagecopyresized (cel, źródło, x_celu, y_celu, x_źródła, y_źródła, wys_celu, szer_celu, wys_źródła, szer_źródła); y_źródła x_źródła szer_źródła wys_źródła y_celu cel x_celu szer_celu wys_celu źródło
9.4. Korzystanie z plików tymczasowych w formacie GD2 W przypadku wykonywania dużej ilości operacji na fragmentach obrazków, oraz konieczności czasowego przechowania obdazków na dysku, warto skorzystać z naturalnego formatu zapisu obrazów biblioteki GD. Format ten nie jest skompresowany (opcjonalnie można włączyć kompresję bezstratną), więc obrazki zajmują na dysku sporo miejsca, ale za to są bardzo szybko zapisywane i odczytywane. Dzięki przejściowemu zapisaniu obrazów na dysk, możemy znacznie ograniczyć zużycie pamięci przez skrypt. Wynika to z faktu, że obrazek znajdujący się w pamięci (załadowany z dysku lub stworzony w skrypcie) jest również nieskompresowany. Format GD2 ma też tę ciekawą cechę, że pozwala na szybkie odczytanie z pliku jedynie fragmentu obrazu, bez potrzeby ładowania całości do pamięci. Zapisu obrazka w formacie GD dokonujemy funkcją imagegd2: imagegd2($obrazek, $nazwa_pliku, $rozmiar_kawałka, $typ); gdzie: obrazek zmienna typu zasób identyfikująca obrazek, nazwa_pliku nazwa pliku do zapisu, można jej nie podać, wtedy plik zostanie wysłany do przeglądarki klienta, ale nie jest to dobry pomysł... rozmiar_kawałka obrazek w formacie GD2 zapisany jest jako zestaw podobrazów o podanym rozmiarze, podanie 0 powoduje użycie domyślnego rozmaru ustalonego przez bibliotekę, typ IMG_GD2_RAW lub IMG_GD2_COMPRESSED, domyślnie ten pierwszy.
Obrazek w formacie GD2 zapisany na dysku ładujemy funkcją imagecreatefromgd2(). Oto sposób użycia: $obrazek = imagecreatefromgd2('gdzieś/jakiś/plik.gd2'); Obrazki w formacie GD2 ładują się znacznie szybciej niż w innych formatach. Można też wykorzystać wcześniej wspomnianą, unikalną możliwość załadowania jedynie fragmentu obrazka, korzystając z funkcji imagecreatefromgd2part(): $obrazek = imagecreatefromgd2part(plik, x, y, wysokość, szerokość); W ten sposób można wczytać do pamięci prostokątny fragment obrazka poczynając od wskazanego piksela (x, y) (lewy górny róg), o podanej w pikselach wysokości i szerokości. Szczególnie dużą oszczędność pamięci (i czas ładowania) osiągniemy, gdy wycinamy mały fragment z dużego obrazka.
9.5. Filtry obrazu Biblioteka GD posiada w swoim asortymencie funkcji również tzw. filtry obrazu, a więc rozliczne operacje znane nam z programów graficznych. Funkcja imagefilter() operuje zawsze na całym wskazanym obrazku, więc w razie konieczności przefiltrowania fragmentów, trzeba zakombinować z funkcjami z rodziny imagecopy. Sama funkcja nie tworzy w wyniku kopii obrazka, operuje na wskazanym oryginale. Oto sposób użycia funkcji: imagefilter(obrazek, filtr, p1, p2, p3); A oto dostępne filtry i znaczenie opcjonalnych parametrów p1, p2 i p3: IMG_FILTER_NEGATE negacja obrazka, parametry są ignorowane, IMG_FILTER_GRAYSCALE konwersja obrazka do odcieni szarości, parametry są ignorowane, IMG_FILTER_BRIGHTNESS zmiana jasności obrazka, p1 to nowy poziom jasności z zakresu od -255 do +255, wartości dodatnie zwiększają jasność, pozostałe są ignorowane, IMG_FILTER_CONTRAST zmiana kontrastu obrazka, p1 to nowy poziom kontrastu z zakresu od -255 do +255, wartości ujemne zwiększają kontrast, pozostałe parametry są ignorowane, IMG_FILTER_COLORIZE koryguje zawartość składowych RGB w obrazku. p1, p2 i p3 to wartości korekcyjne składowych RGB z zakresu od -255 do +255, wartości dodatnie zwiększają zawartość danej składowej,
IMG_FILTER_EDGEDETECT uwydatnia krawędzie i kontury, niestety bez regulacji, parametry są ignorowane, IMG_FILTER_EMBOSS efekt płaskorzeźby, niestety również bez regulacji, parametry są ignorowane, IMG_FILTER_GAUSSIAN_BLUR rozmycie obrazka metodą konwolucji z macierzą o obwiedni krzywej Gaussa, niestety żadnej regulacji, parametry są ignorowane, IMG_FILTER_SELECTIVE_BLUR inny rodzaj rozmycia, osiąga się efekt nieostrego zdjęcia, znów bez regulacji, IMG_FILTER_SMOOTH wygładzenie obrazka, wartości dodatnie to mniejsze wygładzenie, przydatny zakres parametru p1 to <-8, +8>, IMG_FILTER_MEAN_REMOVAL odjęcie od obrazka jego wartości średniej kolorów. Regulacji brak.
9.6. Praca z przezroczystością Biblioteka GD pozwala na używanie przezroczystości. Każdy kolor używany do kreślenia może być w regulowanym stopniu przezroczysty. Takie kolory rezerwujemy funkcją imagecolorallocatealpha(). Działa ona w ten sposób jak imagecolorallocate(), ale pozwala na podanie stopnia przezroczystości koloru od 0 (zupełnie nieprzezroczysty) do 127 (maksymalnie przezroczysty). $kolor = imagecolorallocatealpha(r, g, b, przezr); Taki kolor możemy w razie potrzeby zwolnić funkcją imagecolordeallocate(). Praca z półprzezroczystmi kolorami ma w zasadzie sens wyłącznie na obrazkach w trybie TrueColor, choć dwustanowa przezroczystość może się przydać i w obrazach paletowych. Tryb względny i bezwzględny przezroczystości Te dwa tryby powodują inną interpretację przezroczystości koloru przy operacjach rysunkowych. Zacznijmy od trybu względnego, jako bardziej intuicyjnego tu przezroczystość jest interpretowana względem tego, co aktualnie znajduje się na obrazku w miejscu rysowania. Jeżeli mamy stworzony świeży obrazek (a więc czarne tło) i narysujemy koło kolorem czerwonym o przezroczystości 64 (50%), to jak się można spodziewać, dostaniemy koło brązowe. Przezroczystość wynikowego brązowego piksela będzie zerowa wartość przezroczystości koloru koła została zjedzona w procesie nakładania.
Inaczej zachowuje się tryb bezwzględny przezroczystości. Tutaj wartość przezroczystości koloru zostaje wstawiona bezwzględnie jako przezroczystość piksela. Przezroczystość zatem będzie zachodziła nie wobec dotychczasowej treści obrazka, ale wobec tła, na jakim znajdzie się obrazek na stronie WWW. Zostanie ona więc obliczona nie przez PHP, ale przez przeglądarkę internetową klienta. To samo koło narysowane w przykładzie, nie będzie brązowe, ale będzie przez nie widać tło, oczywiście podbarwione na czerwono. Poniższe rysunki ilustrują zagadnienie (tłem strony jest czarno-biała szachownica). przezr. względna przezr. bezwzględna Tryb przezroczystości przełączamy funkcją imagealphablending(). Trybem domyślnym jest przezroczystość względna (TRUE), bezwzględną osiągamy przez ustawienie wartości na FALSE. imagealphablending($obrazek, FALSE);
Należy pamiętać o tym, że nie każdy format obrazka obsługuje płynną przezroczystość, z formatów sieciowych jest to wyłącznie PNG. Aby wyemitować do obrazka PNG informację o przezroczystości, należy na nim wywołać (najlepiej od razu po stworzeniu) funkcję imagesavealpha(). imagesavealpha($obrazek, TRUE); Przykład przezroczystości bezwzględnej z poprzedniej strony powstał właśnie po takim wywołaniu funkcji imagesavealpha(). Czarne tło obrazka, jakie powstaje po jego stworzeniu, ma wartość przezroczystości 0. Jeżeli chcemy mieć całkowicie przezroczyste tło na starcie, powinniśmy użyć na całym obszarze obrazka imagefilledrectangle(), z kolorem o maksymalnej przezroczystości, co da w przykładzie poniższy efekt.