Funkcje do tworzenia złożonych gradientów są dość obszerne, my tutaj postaramy się nauczyć podstaw tworzenia prostych gradientów polegających na liniowym przejściu pomiędzy kolorami. Nauczymy się też operować na pikselach - pobierać oraz modyfikować ich wartości.
Tworzymy gradient
Popatrzmy na poniższy obrazek:To prosty gradient wygenerowany bezpośrednio w PHP za pomocą jednej prostej pętli for. Aby móc tworzyć podobne obrazki za pomocą swoich funkcji trzeba zrozumieć zasadę działania takiego mechanizmu.
Najprostrzym sposobem na wygenerowanie liniowego przejścia jest pętla przechodząca pionowo lub poziomo inkrementująca się o jeden piksel wraz z każdym kolejnym przebiegiem. W każdym przebiegu jednocześnie zmniejszana lub zwiększana musi być wartość zadanego przez nas koloru.
Jak wiemy - kolory definiujemy za pomocą podawania ich odpowiednich wartości liczbowych w palecie RGB. Skoro więc są to zwykłe dane liczbowe, nic nie stoi na przeszkodzie, aby wykonywać na nich dowolne operacje matematyczne. Aby zrozumieć zasadę działania, stwórzmy sobie obrazek o szerokości 600px i wysokości 256px:
- $width = 600;
- $height = 256;
- $image = imagecreatetruecolor($width, $height);
następnie stwórzmy pętlę for, która będzie przebiegać pionowo po naszym obrazku:
- for($i=0; $i < $height; $i++)
- {
- // ....
- };
Jak widzimy pętla przebiegać będzie po koleji po "wierszach" obrazka, począwszy od wiersza 0, na ostatnim wierszu (w tym przypadku 255) kończąc. Dodajmy teraz do naszej pętli następujący kod:
- for($i=0; $i < $height; $i++)
- {
- $color = imagecolorallocate($image, $i, $i, $i);
- imageline($image, 0, $i, $width, $i, $color);
- };
W każdym kolejnym przebiegu definiujemy nowy kolor, którego wartość będzie rosła liniowo wraz z inkrementacją zmiennej $i. Następnie rysujemy linię po całej szerokości naszego obrazka, o współrzędnej Y pobieranej również ze zmiennej $i. W każdym wierszu naszego obrazka będzie więc rysowana pozioma linia o wartości koloru rosnącej wraz z każdym przebiegiem pętli, aż do uzyskania końcowego miejsca na obrazie (255px w pionie).
Przetestujmy w praktyce:
- <?php
- $width = 600;
- $height = 256;
- $image = imagecreatetruecolor($width, $height);
- for($i=0; $i < $height; $i++)
- {
- $color = imagecolorallocate($image, $i, $i, $i);
- imageline($image, 0, $i, $width, $i, $color);
- };
- header('Content-Type: image/png');
- imagepng($image);
- imagedestroy($image);
- ?>
Wynikiem będzie najprostszy z możliwych gradient:
Zmodfikujmy teraż nasz kod, tak aby pozwalał na wygenerowanie gradientu dla dowolnego rozmiaru obrazka - póki co mamy tu ograniczenie do 255px, bo tylko tyle maksymalnie może przyjąć wartość RGB. Musimy więc teraz w jakiś sposób obliczyć co ile pikeli mamy zwiększać wartość naszego koloru w zależności od całkowitej wysokości naszego obrazu.
Wykonany to poniższym sposobem:
- for($i=0; $i<$height; $i++)
- {
- $color = floor($i * 255 / $height);
- $color = imagecolorallocate($image, $color, $color, $color);
- imageline($img, 0, $i, $width, $i, $color);
- };
Wartość koloru obliczamy algorytmem:
- współrzędnaY * 255 / całkowita_wysokość obrazka
Funkcja floor() zakokrągla nam wynik do najbliższej, najniższej wartości całkowitej, np. floor(3.14) da nam 3.
Zobaczmy teraz, czy to zadziała, np. dla obrazka o wymiarach 600x450px:
- <?php
- $width = 600;
- $height = 450;
- $image = imagecreatetruecolor($width, $height);
- $white = imagecolorallocate($image, 255, 255, 255);
- for($i=0; $i<$height; $i++)
- {
- $color = floor($i * 255 / $height);
- $color = imagecolorallocate($image, $color, $color, $color);
- imageline($image, 0, $i, $width, $i, $color);
- };
- imagestring($image, 5, 140, 210, 'RGB($color++, $color++, $color++)', $white);
- header('Content-Type: image/png');
- imagepng($image);
- ?>
Jak widać działa. Gradient rozciągnął się na całą wysokość obrazu.
Nasze linearne wypełnienie jest jednak trochę nudne prawda? Dodajmy mu trochę koloru.
Jak to zrobić? Otóż w chwii obecnej zwiększamy w naszej pętli wartości wszystkich składowych RGB jednocześnie, co za tym idzie nasz gradient generuje się liniowo od koloru czarnego (RGB = 0,0,0) do koloru białego (RGB = 255, 255, 255). Zostawmy więc np. wartości koloru zielonego i niebieskiego w spokoju, a zwiększajmy jedynie wartość składowej czerwonej:
- <?php
- $width = 600;
- $height = 450;
- $image = imagecreatetruecolor($width, $height);
- $white = imagecolorallocate($image, 255, 255, 255);
- for($i=0; $i<$height; $i++)
- {
- $color = floor($i * 255 / $height);
- $color = imagecolorallocate($image, $color, 0, 0);
- imageline($image, 0, $i, $width, $i, $color);
- };
- imagestring($image, 5, 200, 210, 'RGB($color++, 0, 0)', $white);
- header('Content-Type: image/png');
- imagepng($image);
- ?>
Wynik:
A teraz dla składowej zielonej:
- <?php
- $width = 600;
- $height = 450;
- $image = imagecreatetruecolor($width, $height);
- $white = imagecolorallocate($image, 255, 255, 255);
- for($i=0; $i<$height; $i++)
- {
- $color = floor($i * 255 / $height);
- $color = imagecolorallocate($image, 0, $color, 0);
- imageline($image, 0, $i, $width, $i, $color);
- };
- imagestring($image, 5, 200, 210, 'RGB(0, $color++, 0)', $white);
- header('Content-Type: image/png');
- imagepng($image);
- imagedestroy($image);
- ?>
I niebieskiej:
- <?php
- $width = 600;
- $height = 450;
- $image = imagecreatetruecolor($width, $height);
- $white = imagecolorallocate($image, 255, 255, 255);
- for($i=0; $i<$height; $i++)
- {
- $color = floor($i * 255 / $height);
- $color = imagecolorallocate($image, 0, 0, $color);
- imageline($image, 0, $i, $width, $i, $color);
- };
- imagestring($image, 5, 200, 210, 'RGB(0, 0, $color++)', $white);
- header('Content-Type: image/png');
- imagepng($image);
- imagedestroy($image);
- ?>
Jak widać, mamy tutaj duże pole do popisu odnośnie miksowania kolorów.
Warto też zauważyć, że tym sposobem możemy zabawić się również z przezroczystością modyfikujac liniowo wartość kanału alpha.
ImageColorAt() - pobieranie wartości koloru z piksela
Dzięki funkcji imagecolorat() możemy pobrać wartość koloru dla dowolnego piksela w obrazie. Zwracana wartość to indeks koloru w postaci liczby integer, musimy użyć przesunięć bitowych, aby uzyskać wartości poszczególnych składowych. Użycie funkcji przedstawia się następująco:
- $rgb = imagecolorat($image, $x, $y)
gdzie
- $image - uchwyt do obrazka
- $x - współrzędna X piksela
- $y - współrzędna Y piksela
Wartość RGB pobierzemy tak:
- $image = imagecreatefromjpeg('angelina.jpg');
- $rgb = imagecolorat($image, 10, 15);
- $pixel['r'] = ($rgb >> 16) & 0xFF;
- $pixel['g'] = ($rgb >> 8) & 0xFF;
- $pixel['b'] = $rgb & 0xFF;
Możemy stworzyć sobie do tego prostą funkcję:
- function getRgb($image, $x, $y)
- {
- $rgb = imagecolorat($image, $x, $y);
- $pixel['r'] = ($rgb >> 16) & 0xFF;
- $pixel['g'] = ($rgb >> 8) & 0xFF;
- $pixel['b'] = $rgb & 0xFF;
- return $pixel;
- }
Sprawdźmy w praktyce jak to działa.
Wczytajmy zdjęcie z Angeliną, nad którym pastwiliśmy się w tym artykule i pobierzmy wartości kilku pixeli, po czym wyświetlmy te wartości na obrazku:
- <?php
- function getRgb($image, $x, $y, $show = true)
- {
- $white = imagecolorallocate($image, 255, 255, 255);
- $rgb = imagecolorat($image, $x, $y);
- $pixel['r'] = ($rgb >> 16) & 0xFF;
- $pixel['g'] = ($rgb >> 8) & 0xFF;
- $pixel['b'] = $rgb & 0xFF;
- // pobieramy wartości RGB do tablicy
- if($show)
- {
- imageellipse($image, $x, $y, 10, 10, $white);
- // rysujemy elipsę w miejscu badanego pixela
- $str = 'R:'.$pixel['r'].' G:'.$pixel['g'].' B:'.$pixel['b'];
- imagestring($image, 5, $x + 5, $y + 5, $str, $white);
- // wyświetlamy wartość w miejscu badanego pixela
- }
- return $pixel; // zwracamy tablicę z wartościami RGB
- }
- $image = imagecreatefromjpeg("angelina.jpg");
- $pixel_color[1] = getRgb($image, 100, 100);
- $pixel_color[2] = getRgb($image, 400, 340);
- $pixel_color[3] = getRgb($image, 130, 30);
- // pobieramy RGB pixeli
- header('Content-type: image/png');
- ImagePNG($image);
- imagedestroy($image);
- ?>
Wynik:
ImageSetPixel() - ustawianie wartości RGB piksela
Analogicznie do funkcji pobierającej dane o wartości piksela mozemy zadziałać w drugą stronę - ustawić wartości pikseli. Służy do tego omawiana funkcja, której użycie wygląda tak:
- imagesetpixel($image, $x, $y, $color)
gdzie:
- $image - uchwyt do obrazka
- $x - współrzędna X piksela
- $y - współrzędna Y piksela
- $color - kolor jaki ustawiamy
Przykładowo, zmieńmy wartości kilku pikseli w lewym górnym rogu obrazka.
Jest tam akurat czarne tło - zmienimy kilka pixeli na kolor biały.
- <?php
- $image = imagecreatefromjpeg("angelina.jpg");
- $white = imagecolorallocate($image, 255, 255, 255);
- imagesetpixel($image, 20, 10, $white);
- imagesetpixel($image, 30, 20, $white);
- imagesetpixel($image, 4, 50, $white);
- imagesetpixel($image, 50, 70, $white);
- imagesetpixel($image, 10, 17, $white);
- imagesetpixel($image, 44, 2, $white);
- imagesetpixel($image, 80, 4, $white);
- imagesetpixel($image, 65, 12, $white);
- header('Content-type: image/png');
- ImagePNG($image);
- imagedestroy($image);
- ?>
Tym sposobem postawiliśmy na obrazie kilka małych "kropek":
Oczywiście takich modyfikacji nie wykonuje się ręcznie dla każdego piksela oddzielnie - do tego buduje się funkcje i pętle robiące to "hurtowo". Zaprezentowałem tutaj jedynie prosty przykład mający na celu pokazać, że funkcja taka istnieje i jak jej używać.
Przy wykorzystaniu faktu pobierania wartości dowolnych pikseli i ustawiania im własnych wartości można uzyskać naprawdę rozudowane możliwości. Zachęcam do eksperymentowania we własnym zakresie.
Brak komentarzy:
Prześlij komentarz
Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)