Náhled obrázku v PHP (OOP)
Samozřejmostí každého redakčního systému nebo publikačního systému, který pracuje s obrázky, je vytvářet náhledy. Článek popisuje postup při vývoji takové třídy.
Každý web co zobrazuje na jedné stránce více obrázků, např. jako ilustrační foto u článků, nutně potřebuje vytvářet náhledy.
Pro ilustraci si představte výpis článků: 10 článků, 10 fotek, průměrně může mít jedna fotka v detailu 100kb nebo i mnohonásobně více. Když se budu snažit ve výpisu zobrazit náhled zápisem html kódu <img src="foto1.jpg" width="100px" height="150px" /> ke klientovi (do prohlížeče) bude stále stahován obrázek s plnou velikostí, takže v nejlepším případě si čtenář počká než se stáhne 1MB a poté se mu teprve náhledy zobrazí.
Protože jsem fanda objektového programování, popíšu postup, jak jsem psal třídu na vytváření náhledu obrázku. Nejprve jsem si specifikoval co taková třída má umět, co od ní chci a jak s ní chci pracovat. Třída pracuje s obrázky již nahranými na server, upload budeme muset zajisti před samotnou akcí.
Postup při psaní třídy na vytváření náhledů obrázků
Chci, aby třída vzala detail obrázku, zmenšila ho a uložila jako nový obrázek, přitom chci stanovit maximální výšku a šířku, popřípadě kvalitu obrázku.
Určím nejprve základní vlastnosti a metody, chci aby bylo možné thumbnail vytvořit a nebo zobrazit na obrazovku. K tomu budu potřebovat vypočítat jeho výslednou výšku a šířku getComputedSize() a zjistit jeho typ getMimeType().
- <?
- class Thumb {
- public $source, $WMax, $HMax, $quality;
- private $imagesize, $computedsize;
- public function __construct($source, $WMax=1000, $HMax=1000, $quality=60) {
- $this->source = $source;
- $this->WMax = $WMax;
- $this->HMax = $HMax;
- $this->quality = $quality;
- }
- public function createThumb($destionation) { }
- public function showThumb() { }
- private function getMimeType() { }
- private function getComputedSize() { }
- }
- ?>
V konstruktoru třídy přiřazuji základní vlastnosti pomocí $this. Defaultně jsem nastavil maximální výšku a šířku na 1000 a kvalitu na 60.
Začnu od lesa a to metodami showThumb a createThumb, k zobrazení nebo uložení obrázku používáme vestavěnou funkci php imagegif, imagejpeg nebo imagepng. Jako vstupní parametr je výsledek imagecreate, a v případě zadání druhého parametru bude výstupem soubor, při absenci tohoto parametru bude výstupem obrazovka. Při výpisu obrázku gif by vypadal kód funkce takhle:
- header ("Content-type: image/gif");
- imagegif($image);
- imagedestroy($image);
- exit;
Obdobně jsou řešené jpg a png, pro usnadnění práce použijeme vytváření uživatelských funkcí pomocí call_user_func_array.
Zvláštností funkcí imagejpeg a imagepng je možnost stanovení kvality výsledného obrázku. Ještě větší zvláštností je, že u imagepng to nefunguje vůbec. Další problém je, že se stanovují odlišně, imagejpeg přijímá hodnoty od 0 do 100 a chápe číslo jako výši kvality, tedy 100 je maximální kvalita, narozdíl imagepng, která stanovuje výši komprese, tedy přesně opačně od 0 do 9, 9 je maximální komprese a nejméně kvalitní obrázek. My chceme, aby naše třída vnímala kvalitu jako procentní stupeň, proto vytvoříme převodní funkci getComputedQuality(). Výhodou je že funkci call_user_func_array můžeme volat s polem parametrů.
- <?
- class Thumb {
- public $source,$WMax, $HMax, $quality;
- private $imagesize, $computedsize;
- public function __construct($source,$WMax=1000, $HMax=1000, $quality=60) {
- $this->source = $source;
- $this->WMax = $WMax;
- $this->HMax = $HMax;
- $this->quality = $quality;
- }
- public function createThumb($destination) {
- $image=$this->getSource();
- $params=array($image, $destination);
- if ($this->getMimeType()=="jpeg" || $this->getMimeType()=="png") $params[]=$this->getComputedQuality();
- call_user_func_array('image'.$this->getMimeType(), $params);
- imagedestroy($image);
- }
- public function showThumb() {
- $image=$this->getSource();
- $params=array($image);
- if ($this->getMimeType()=="jpeg" || $this->getMimeType()=="png") {
- $params[]=NULL;
- $params[]=$this->getComputedQuality();
- }
- header ("Content-type: ".$this->getImageSize('mime'));
- call_user_func_array('image'.$this->getMimeType(), $params);
- imagedestroy($image);
- exit;
- }
- private function getSource() {
- }
- public function getMimeType() {
- if (!$this->imagesize) $this->imagesize=getimagesize($this->source);
- switch ($this->imagesize[2]) {
- case 1:
- return 'gif';
- break;
- case 2:
- return 'jpeg';
- break;
- case 3:
- return 'png';
- break;
- default:
- return $this->imagesize['mime'];
- break;
- }
- }
- public function getImageSize($size=null) {
- }
- public function getComputedSize($size=null) {
- }
- public function getComputedQuality() {
- if (!$this->quality>0) return null;
- if ($this->getMimeType()=="jpeg") return $this->quality;
- elseif ($this->getMimeType()=="png") {
- $q=round((100-$this->quality)/10);
- if ($q>9) $q=9;
- return $q;
- }
- }
- }
- ?>
Teď už zbývá vypočítat konečnou šířku a výšku obrázku a funkce getSource vrací změnšený obrázek ke zpracování (uložení, zobrazení).
V ukázce byl použit kód z článku Rekurzivní procházení adresářů s filtrem souborů. Ještě snad zmíním, že nejen funkce imagepng nefunguje jak by měla, ale ani imagegif. Přesto, že deklaruje, že přijímá hodnotu null místo destinace obrázku, nesmí být druhý parametr zadán, pokud chceme výpis na obrazovku. Proto je v kódu tento obrat:
- $params=array($image);
- if ($this->getMimeType()=="jpeg" || $this->getMimeType()=="png") {
- $params[]=NULL;
- $params[]=$this->getComputedQuality();
- }
- header ("Content-type: ".$this->getImageSize('mime'));
- call_user_func_array('image'.$this->getMimeType(), $params);
Pole params v případě gif obrázků nesmí být rozšířeno!
komentáře
RSS Komentáře
- pixely – jak to souvisí s tématem
- png – bezztrátová komprese, ok, jak je toho dosaženo? co tedy znamená v manuálu:
quality – Compression level: from 0 (no compression) to 9. viz. http://cz.php.net/imagepng



Atributy IMG WIDTH a HEIGHT se uvádí v pixlech bez jednotek, nebo v procentech. Jednotka px se používá ve stylech.
PNG je bezztrátový formát a číslo je tedy opravdu jen úroveň komprese (stejně jako třeba u ZIPu). Nevyjadřuje tedy kvalitu, ta je vždy stejná.