Portál o technologiích a vývoji

Obrázky ve webových aplikacích – Pokročilejší manipulace

Autor: Adam Klvač Datum: 3.10.2013 Počet shlédnutí: 3 941 243x

Ořezávání a rotace obrázku většinou pro účely avataru stačí. Jakmile ale začnete s provozem webových galerií, budete se možná potýkat s problémem, kdy se na vašich obrázcích bude někdo jakýmkoliv způsobem přiživovat – nasadíte vodoznaky. Také může být užitečné generovat grafy, bannery, nebo CAPTCHA kódy. V té chvíli už si s ořezáváním nevystačíte a budete muset zvládnout obrázky nějakým způsobem generovat. Zmíním se také o průhlednosti, kvůli které jsem strávil nad dokumentací už pěkných pár večerů.

Vkládání vodoznaku

Vložení vodoznaku je poměrně často používané. Technicky to znamená vzít obrázek vodoznaku a vložit jej do nahrávaného obrázku. Zde už je zpravidla nutné řešit průhlednost, což si později ještě objasníme. Funkcí imagecopymerge jsme umístili vodoznak 5px od levého dolního okraje obrázku.

// Rozměry obrázku
$imageW = imagesx($image);
$imageH = imagesy($image);

// Rozměry vodoznaku
$watermarkW = imagesx($watermark);
$watermarkH = imagesy($watermark);

imagecopymerge(
    $image, $watermark,
    $imageW - $watermarkW - 10 , $imageH - $watermarkH - 5,
    0, 0, $watermarkW, $watermarkH, 100
);

Vykreslování obrazců a textu

 

Pro účely tvorby CAPTCHA kódu (známý opis kódu z obrázku vyžadovaný při registraci) se využívá toho, že GD může vykreslit někam na plátno text. Dokáže mu nastavovat barvu a dokáže využít dodaného TTF fontu. Také je možné vykreslit geometrické obrazce, což může být šikovné třeba při generování bannerů na externí webové stránky, nebo pro tvorbu grafů. Silně doporučuji všechny takto generované obrázky (to se týká veškerého zpracování) ukládat do nějaké cache, protože generování za běhu je náročné na čas i prostředky.

Funkce imagefttext vloží na zadané souřadnice text o určité velikosti, dokáže jej také otáčet o zadaný úhel.

$fontSize = 24;
$angle = 45;
$x = 600;
$y = 300;
$color = 0xFF0000;
$fontFile = __DIR__ . "/Ubuntu.ttf";
$text = "Hello World";

imagefttext(
    $image, $fontSize,
    $angle, $x, $y,
    $color, $fontFile,
    $text
);

Na souřadnice 600×300 jsme umístili červený nápis Hello World o velikosti 24px, otočený o 45° (úhly jsou počítány proti směru hodinových ručiček). Soubor s fontem uvádějte s absolutní cestou, jinak jej PHP nemusí najít (nehledá ve stejném adresáři). Konstanta __DIR__ obsahuje cestu k adresáři se skriptem, ve kterém se nacházíme. Ve starších verzích byla pouze konstanta __FILE__, novou konstantu je tedy možné nahradit zápisem:

$fontFile = dirname(__FILE__) . "/Ubuntu.ttf";

Následujícími funkcemi můžeme vykreslovat geometrické obrazce. Název obsahující filled indikuje, že obrazec bude vyplněný.

// Elipsa se středem na 200x300 s rozměry 100x50 (zelená, nevyplněná)
imageellipse($image, 200, 300, 100, 50, 0x00FF00);

// Obdélník se středem na 500x400 s rozměry 40x20 (modrý, vyplněný)
imagefilledrectangle($image, 500, 400, 540, 420, 0x0000FF);

Pokud budeme potřebovat, aby byl obrazec průhledný, musíme získat index barvy funkcí imagecolorallo­catealpha. Ta přijímá jako první parametr obrázek, další 3 postupně jako kanály RGB (0–255) a 4. důležitý parametr – průhlednost. Ta může mít hodnotu od 0 do 127, s tím, že 0 je neprůhledný, 127 pak způsobí úplnou neviditelnost.

Průhlednost

Dostáváme se k nejméně veselé části práce s obrázky. Můžete narazit na problém, kdy například průhledné PNG při zmenšení ztratí průhlednost, zcela jistě budete mít problém s umístěním průhledného vodoznaku.

Zmenšování průhledného PNG se liší od již uvedeného postupu tím, že plátnu se zmenšeným obrázkem nastavíme průhlednost. Vytvoříme si barvu, která je průhledá a obdélník s touto barvou aplikujeme na celý rozměr plátna.

$resized = imagecreatetruecolor($newWidth, $newHeight);
imagealphablending($resized, false);
imagesavealpha($resized,true);
$transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127);
imagefilledrectangle($resized, 0, 0, $newWidth, $newHeight, $transparent);

Teprve po tomto vytvoření plátna na něj umístíme zmenšený obrázek.

S vodoznaky to je horší. Nelze jednoduše přímo vložit vodoznak do obrázku, ztrácí se nám tím průhlednost (pozadí vodoznaku je černé). Tedy pokud neuložíme vodoznak jako PNG-8 – toto řešení mi bez problému fungovalo, ale není to ideální. Problém je, že často dostávám od grafiků připravené vodoznaky a ty jsou ve standardním PNG a já je konverzí nechci ničit (vypadají ohavně). Proto se nabízí druhé řešení, které jsem kdysi objevil v komentářích dokumentace PHP.

$x = imagesx($image) - imagesx($watermark) - 10;
$y = imagesy($image) - imagesy($watermark) - 10;

// Výřez z obrázku, který poslouží jako pozadí vodoznaku
$cut = imagecreatetruecolor(imagesx($watermark), imagesy($watermark));
imagecopy(
    $cut, $image,
    0, 0, $x, $y,
    imagesx($watermark), imagesy($watermark)
);

// Vložíme na výřez vodoznak
imagecopy(
    $cut, $watermark,
    0, 0, 0, 0,
    imagesx($watermark), imagesy($watermark)
);

// Vložíme výřez s vodoznakem na obrázek
imagecopymerge(
    $image, $cut,
    $x, $y, 0, 0,
    imagesx($watermark), imagesy($watermark), 100
);

Na běžné vodoznaky v PNG je tato metoda funkční. Neměl jsem potíže ani s GIFy, opět je ale nutné, při jejich zmenšení, vkládat zmenšený obrázek na průhledné plátno, což jsem již ukazoval na začátku této kapitoly. S animovanými GIFy je situace poněkud horší.

Štítky: | | |

Žádné komentáře

Poslat komentář

Vaše e-mailová adresa nebude zveřejněna.