Myšlena práce s fotkami na straně serveru…
Co bylo třeba vyřešit:
- zmenšení fotek
- záloha velkých originálů
- vytvoření náhledů
- vytvoření úvodní fotky pro danou složku
- (vyplynulo až později) „kešování“ dat, pro dostatečně rychlé procházení fotoalbem
Všechno se děje vlastně sériově. Vždy se ověří, zda danou operaci je nutné dělat a pokud ne, tak se vynechá. Zároveň se dané části kešují, jelikož z praxe vyplynulo, že i když není třeba nic dělat, tak samotné ověřování trvá řády jednotek až desítek sekund. A na to nikdo čekat nechce.
Poznámka: Vím, že kód níže není optimální a zasloužil by jistou refaktorizaci, ale to bych tento článek a především fotoalbum nenapsal ani za rok (Ano píšu ho ve svém volném čase a pro dobro věci. Ne pro peníze.). A taky se omlouvám za ne úplně 100% prezentaci kódu, ale neznám lepší plugin do WordPressu, který by to zvládal dokonale.
# VYTÁHNEMKE SI SLOŽKY A K NIM ÚVODNÍ FOTKU (samozřejmě jen pokud již nejsou v cache) $value = $cache->load("folders-{$path}"); if ($value === NULL) { $i=0; foreach (Finder::findDirectories('*')->exclude('[0-9][0-9][0-9]', '_big')->in($path)->orderByName('DESC') as $key => $file) { $this->template->dirs[$i]['name'] = $this->I->getNameFromPath(substr($key, strlen(ALBUM_PATH)).'/'); // vytahneme si small_home foreach (Finder::findFiles('_small_home.png')->in($key) as $key_home => $file_home) { $this->template->dirs[$i]['small_home'] = ALBUM_DIR . substr($file_home->getPath(), strlen(ALBUM_PATH)) . '/_small_home.png'; } $this->template->dirs[$i++]['pos'] = substr($key, strlen(ALBUM_PATH)+5); } $cache->save("folders-{$path}", $this->template->dirs); } else { $this->template->dirs = $value; } # VYTÁHNEMKE SI FOTKY (samozřejmě jen pokud již nejsou v cache) $value = $cache->load("files-f-{$path}"); if ($value === NULL) { # POKUD EXISTUJÍ TAKOVÉ, KTERÉ MAJÍ VĚTŠÍ STRANU VĚTŠÍ NEŽ 1200PX, TAK JE: # - ZMENŠÍME # - VELKÉ ORIGINÁLY ZAZÁLOHUJEME # - PŘENESEME EXIF INFORMACE foreach (Finder::findFiles('*.jpg', '*.jpeg')->exclude('*_small*')->dimensions('>1200', '>1200')->in($path) as $key => $file) { $image = @Image::fromFile($key); // ini_set(‘gd.jpeg_ignore_warning’, 1); $image->resize(1200, 1200, Image::SHRINK_ONLY | Image::FIT); $ex = exif_read_data($key, 'EXIF'); if(!empty($ex['Orientation'])) { switch($ex['Orientation']) { case 8: $image->rotate(90, 0); break; case 3: $image->rotate(180, 0); break; case 6: $image->rotate(-90, 0); break; } } $image->sharpen(); $s = $key; $d = $file->getPath() . '/_big/' . $file->getFilename(); $fd = new SplFileInfo($file->getPath() . '/_big/'); if (!$fd->isDir()) mkdir($file->getPath() . '/_big/'); rename($s, $d); $image->save($key); // přeuložíme EXIF informace - použita externí knihovna PelJpeg $input_jpeg = new PelJpeg($d); $exif = $input_jpeg->getExif(); if ($exif != null) { $output_jpeg = new PelJpeg($key); $output_jpeg->setExif($exif); $output_jpeg->saveFile($key); } } # DÁLE VYTVOŘÍME MALÉ NÁHLEDY foreach (Finder::findFiles('*.jpg', '*.jpeg')->exclude('*_small*')->exclude($denyFiles) ->filter(function($file) { $file_extension = pathinfo($file->getFilename(), PATHINFO_EXTENSION); $info = new SplFileInfo($file->getPath() . '/' . $file->getBasename('.' . $file_extension) . '_small_500' . '.jpg'); return !$info->isFile(); })->in($path) as $key => $file) { // vytvoření náhledu $image = @Image::fromFile($key); $image->resize(500, 500, Image::SHRINK_ONLY | Image::FIT); $image->sharpen(); $file_extension = pathinfo($file->getFilename(), PATHINFO_EXTENSION); $image->save($file->getPath() . '/' . $file->getBasename('.' . $file_extension) . '_small_500' . '.jpg'); } # DÁLE VYTVOŘÍME ÚVODNÍ NÁHLED, KTERÝ SE BUDE ZOBRAZOVAT MÍSTO OBRÁZKU SLOŽKY $small_home = Image::fromBlank(360, 360, Image::rgb(255, 255, 255, 127)); $i=0; foreach (Finder::findFiles('*.jpg', '*.jpeg')->exclude('*_small*')->exclude($denyFiles) ->filter(function($file) { $info = new SplFileInfo($file->getPath() . '/_small_home.png'); return !$info->isFile(); })->in($path) as $key => $file) { $image = @Image::fromFile($key); $image->saveAlpha(true); $image->resize(250, 250, Image::SHRINK_ONLY | Image::FIT); $blank = Image::fromBlank($image->getWidth()+20, $image->getHeight()+20, Image::rgb(255, 255, 255)); $blank->alphaBlending(true); $blank->saveAlpha(true); $blank->place($image, 10, 10); $blank->rotate(mt_rand(-60, 60), Image::rgb(255, 255, 255, 127)); $blank->sharpen(); $small_home->place($blank, 20+mt_rand(-15, 15), 20+mt_rand(-15, 15)); if ($i++ == 5) { $small_home->resize(200, 200, Image::SHRINK_ONLY | Image::FIT); $small_home->save($file->getPath() . '/_small_home.png', NULL, Image::PNG); $upPath = substr($file->getPath(), 0, strrpos($file->getPath(), '/')+1); $cache->remove("folders-{$upPath}"); // pokud tvoříme náhled, tak smažeme cache předka složky, aby se mi při dalším načtení tato cache obnovila break; } } # A KDYŽ MÁME VŠECHNO PŘIPRAVENO, TAK SI JEŠTĚ JEDNOU NAČTU KOMPLETNÍ INFO, KTERÉ SI PAK ULOŽÍM DO CACHE $i=0; foreach (Finder::findFiles('*.jpg', '*.jpeg')->exclude('*_small*')->exclude($denyFiles)->in($path)->orderByEXIFTime() as $key => $file) { $this->template->files[$i]['key'] = ALBUM_DIR . substr($key, strlen(ALBUM_PATH)); $exif_ifd0 = read_exif_data($file, 'IFD0', 0); $this->template->files[$i]['file'] = date("d.m.y H:i", strtotime($exif_ifd0['DateTime'])); $file_extension = pathinfo($file->getFilename(), PATHINFO_EXTENSION); $tf = @Image::fromFile($file->getPath() . '/' . $file->getBasename('.' . $file_extension) . '_small_500' . '.jpg'); $this->template->files[$i]['w'] = $tf->getWidth(); $this->template->files[$i]['h'] = $tf->getHeight(); $this->template->files[$i++]['pos'] = ALBUM_DIR . substr($file->getPath(), strlen(ALBUM_PATH)) . '/' . $file->getBasename('.' . $file_extension) . '_small_500' . '.jpg'; } $cache->save("files-f-{$path}", $this->template->files); } else { $this->template->files = $value; } |
Jednotlivé části dle mě nemá smysl detailněji popisovat. Je třeba se tím prokousat a pochopit. Pokud by byly dotazy nechť poslouží komentáře.
Jedna konstrukce by šla napsat jednodušeji, jen DEBIAN v současnosti neobsahuje správnou verzi PHP a v té co tam je obsahuje známou chybu…
// Takže místo... $tf = @Image::fromFile($file->getPath() . '/' . $file->getBasename('.' . $file->getExtension()) . '_small_500' . '.jpg'); // musím používat toto... $file_extension = pathinfo($file->getFilename(), PATHINFO_EXTENSION); $tf = @Image::fromFile($file->getPath() . '/' . $file->getBasename('.' . $file_extension) . '_small_500' . '.jpg'); |