Obrázek jsme v minulém dílu ořezali, otočili, přebarvili, vložili vodoznak a popsali jsme jej. Jenže máme pořád jenom jakousi obrazovou mapu typu resource – jak obrázek zobrazíme, nebo uložíme?
Pro jednotlivé formáty existují funkce pro jejich uložení. Jejich povinným parametrem je resource obrázku, pokud neuvedeme další parametry, obrázek se odešle do prohlížeče. Druhým parametrem je název souboru k uložení a třetím kompresní poměr či kvalita.
// Odešleme obrázek k uživateli jako JPG imagejpeg($image); // Uložíme obrázek jako PNG // (kompresní level není uveden - výchozí je 0, tedy bez komprese) imagepng($image, __DIR__ . '/uploads/' . $name . '.png'); // Uložíme obrázek jako JPG v 80% kvalitě imagejpeg($image, __DIR__ . '/uploads/' . $name . '.jpg', 80); // Uložíme obrázek jako GIF (nemá parametr udávající kompresi) imagegif($image, __DIR__ . '/uploads/' . $name . '.gif');
Občas se hodí získat řetězec obrázku jako řetězec. Funkce, která by to umožnila přímo, není. Dá se ale použít output buffering, kterým můžeme výstup skriptu zachytit do proměnné.
// Zahájíme zachytávání výstupu ob_start(); // Odešleme obrázek jako PNG imagepng($image); // Zachytíme jeho výstup do proměnné, k uživateli nic nepřijde $binary = ob_get_clean();
Je také dobré poznamentat, že při odesílání obrázku do prohlížeče uživatele to musíme uvést v HTTP hlavičce.
header('Content-Type: image/gif'); // Pro GIF header('Content-Type: image/jpeg'); // Pro JPG header('Content-Type: image/png'); // Pro PNG
Obrázek smažeme funkcí unlink.
unlink($name);
Ukázka celkového zpracování
Následující ukázkový kód přijme obrázek od uživatele, zmenší jej na polovinu, otočí o 90° doprava a uloží jej v takovém formátu, v jakém přišel.
if($_POST) { // Formulář byl odeslán // Detekce chyby if($_FILES['soubor']['error'] !== UPLOAD_ERR_OK) { // Rozpoznání chybového kódu switch($_FILES['soubor']['error']) { case UPLOAD_ERR_NO_FILE: error("Vyberte, prosím, obrázek."); break; case UPLOAD_ERR_INI_SIZE: error("Obrázek je příliš velký."); break; default: error("Obrázek se nepodařilo nahrát."); break; } } // Kontrola, zda server disponuje extenzí GD if(!function_exists('gd_info')) { // Poněkud matoucí, ale je nutné mít toto // ohlídáno (lepší než prázdná stránka po fatal error) error("Obrázek není možné nahrát."); } // Informace o obrázku $info = getimagesize($_FILES['soubor']['tmp_name']); // Kontrola, zda jde o obrázek if(!$info) { error("Zvolený soubor není platným obrázkem."); } $image = imagecreatefromstring($_FILES['soubor']['tmp_name']); $width = $info[0]; $height = $info[1]; $type = $info[2]; // Kontrola, zda jde o podporovaný typ $allowed = array(IMAGETYPE_GIF, IMAGETYPE_PNG, IMAGETYPE_JPEG); if(!in_array($type, $allowed)) { error("Obrázek musí být ve formátu PNG, JPG nebo GIF."); } // Zmenšení obrázku $newWidth = $width / 2; $newHeight = $height / 2; $resized = imagecreatetruecolor($newWidth, $newHeight); imagealphablending($resized, false); imagesavealpha($resized,true); $transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127); imagefilledrectangle($resized, 0, 0, $newWidth, $newHeight, $transparent); imagecopyresampled( $resized, $image, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height ); imagedestroy($image); $image = $resized; // Rotace obrázku $rotated = imagerotate($image, 360 - 90, 0xFF0000); imagedestroy($image); $image = $rotated; // Vytvoříme jméno obrázku $name = uniqid(); $dbimage = $database->images->insert(array( 'name' => $name )); $name .= $dbimage->id; // Uložení obrázku switch($type) { case IMAGETYPE_PNG: imagepng($image, $name . '.png'); break; case IMAGETYPE_JPEG: imagejpeg($image, $name . '.jpg'); break; case IMAGETYPE_GIF: imagegif($image, $name . '.gif'); break; } }
Protože by mohlo v průběhu zpracování dojít k netušeným chybám, jako všechno doporučuji používat nějakou vrstvu na zachytávání chyb. Pro pohodlnější práci s obrázky se mi velmi osvědčila třída Nette\Image, která obaluje práci s obrázky do objektu a vyhazuje vyjímky, se kterými je mnohem snadnější pracovat.
Práce s obrázky může být poněkud ošemetná a je při ní nutné myslet na všechna rizika. Na druhou stranu to není nic až tak složitého a v dnešní sféře webových aplikací je vlastně nutné umět obrázky zpracovat. Funkcí pro práci s obrázky není nijak mnoho a ukázal jsem zde pouze ty nejzákladnější, s trochou času se ale dá vytvořit například vyobrazení křivek, není nic složitého například přebarvovat obrázky, či je analyzovat (to se může hodit pro hlídání obrázků s pornografickým materiálem). To jsou ale již operace s jednotlivými pixely, což není z technického hlediska tak složité, není to ale podle mne předmětem tohoto článku. Nejdůležitější body – přejmenovat, nevěřit hlavičce s formátem a předpokládat problémy.
Žádné komentáře