Do diskusí na těchto stránkách jsem doplnil možnost zadat adresu vlastních webových stránek. To umožňuje lépe identifikovat autora příspěvku. Pro zpestření vzhledu diskuse a pro rychlejší orientaci v ní se navíc zobrazuje u autora ikona jeho webu. Není to gravatar (které nemám moc rád), ale je to soubor favicon.ico z kořenového adresáře autorova webu (nenahlíží se tedy do stránky na hodnotu <meta> značky shortcut icon).
Se zobrazením ikon je problém v tom, že prohlížeče (přinejmenším IE6) je sice dokáží zobrazit u adresy stránky nebo v oblíbených položkách, ale nedokáží to přímo v kódu stránky. Proto je nutné ikony převést do nějakého běžného formátu. K tomu můžeme použít buď existující knihovny nebo se podívat, jak formát vypadá a napsat si zpracování sami.
Já jsem zvolil druhý případ a vytvořil následující dvě funkce. Funkce imagecreatefromico vezme název souboru s ikonou a požadované rozměry vráceného obrázku a pokusí se v souboru s ikonami najít ikonu daného rozměru s maximálním možným počtem barev. Když se jí to nepovede, tak vezme největší dostupnou ikonu, kterou na požadované rozměry následně převzorkuje.
<?php /** Načtení obrázku z ikony, pokud není k dispozici požadovaný rozměr ikony, tak se na něj převede největší ikona * @param string název souboru * @param int požadovaná šířka ikony * @param int požadovaná výška ikony * @return resource plnobarevný obrázek s ikonou požadovaných rozměrů nebo false v případě chyby * @copyright Jakub Vrána, http://php.vrana.cz/ */ function imagecreatefromico($filename, $width, $height) { $file = file_get_contents($filename); if (!$file) { return false; } $data = unpack("vcount", substr($file, 4, 2)); $read = array(); for ($i=0; $i < $data["count"]; $i++) { $icon = unpack("Cwidth/Cheight/Ccolors/Creserved/vplanes/vbitcount/Vlength/Voffset", substr($file, 6+$i*16, 16)); if (!$icon || !($icon2 = unpack("vibitcount/Vcompression", substr($file, $icon["offset"] + 14, 6)))) { return false; } if (!$read || ($read["width"] == $width && $read["height"] == $height ? $icon["width"] == $width && $icon["height"] == $height && $icon2["ibitcount"] > $read["ibitcount"] : $icon["width"] >= $read["width"] && $icon["height"] >= $read["height"] && $icon2["ibitcount"] >= $read["ibitcount"] )) { $read = $icon + $icon2; } } $im = icon_read(substr($file, $read["offset"] + 40, $read["length"]), $read["width"], $read["height"], $read["ibitcount"], $read["compression"]); if ($read["width"] == $width && $read["height"] == $height) { return $im; } $im2 = imagecreatetruecolor($width, $height); imagecopyresampled($im2, $im, 0, 0, 0, 0, $width, $height, imagesx($im), imagesy($im)); return $im2; } ?>
Pro pohodlné získávání hodnot ze souboru se používá funkce unpack, pro vlastní načtení dat potom uživatelská funkce icon_read:
<?php /** Načtení obrazových dat ikony * @param string obrazová data * @param int šířka obrázku * @param int výška obrázku * @param int počet bitů na pixel * @param int komprese dat - ignoruje se * @return resource plnobarevný obrázek s ikonou * @copyright Jakub Vrána, http://php.vrana.cz/ */ function icon_read($file, $width, $height, $bitcount, $compression = 0) { $im = imagecreatetruecolor($width, $height); imagefilledrectangle($im, 0, 0, $width-1, $height-1, imagecolorallocate($im, 255, 255, 255)); // mohla by se používat transparentnost if ($bitcount <= 8) { $colors = array(); for ($i=0; $i < pow(2, $bitcount); $i++) { $color = unpack("Cblue/Cgreen/Cred", substr($file, 4*$i, 3)); $colors[] = imagecolorallocate($im, $color["red"], $color["green"], $color["blue"]); } $file = substr($file, 4*pow(2, $bitcount)); } for ($y=0; $y < $height; $y++) { for ($x=0; $x < $width; $x++) { $offset = 32*$y*ceil($width*$bitcount/32) + $x*$bitcount; $trans = ord($file[4*$height*ceil($width*$bitcount/32) + 4*$y*ceil($width/32) + floor($x/8)]) & (1 << (7 - $x % 8)); if ($bitcount <= 8) { $byte = ord($file[floor($offset/8)]); $color = $colors[$byte >> (8 - $bitcount - $offset % 8) & (pow(2, $bitcount) - 1)]; } elseif ($bitcount == 16) { $colors = unpack("nbgr", substr($file, $offset/8, 2)); $color = imagecolorallocate($im, round(255/31 * ($colors["bgr"] & 31)), round(255/63 * (($colors["bgr"] >> 5) & 63)), round(255/31 * ($colors["bgr"] >> 11))); } elseif ($bitcount == 32) { $colors = unpack("Cblue/Cgreen/Cred/Calpha", substr($file, $offset/8, 4)); $color = imagecolorallocate($im, 255 - $colors["alpha"] + round($colors["red"] * $colors["alpha"] / 255), 255 - $colors["alpha"] + round($colors["green"] * $colors["alpha"] / 255), 255 - $colors["alpha"] + round($colors["blue"] * $colors["alpha"] / 255)); } else { $colors = unpack("Cblue/Cgreen/Cred", substr($file, $offset/8, 3)); $color = imagecolorallocate($im, $colors["red"], $colors["green"], $colors["blue"]); } if (!$trans) { // $background[0] ^ $colors["red"] prohlížeče nepoužívají imagesetpixel($im, $x, $height - $y - 1, $color); } } } return $im; } ?>
Funkce převezme vlastní obrazová data a informace o nich a pomocí funkce imagesetpixel je umístní do obrázku. Pro získání informací o transparentnosti a indexech barev u paletových obrázků se používají bitové operace.
Pro průhledné body by se dala používat průhledná barva, ta je ale u plnobarevných PNG obrázků problematická. Navíc se obrázek může převzorkovat, při čemž se informace o průhlednosti ztratí. Proto se pro pozadí použije jednoduše bílá barva.
Obrázek vrácený funkcí imagecreatefromico můžeme třeba funkcí imagepng uložit do souboru nebo poslat prohlížeči.
Implementace na těchto stránkách vypadá tak, že po přidání diskusního příspěvku obsahujícího URL se stáhne ikona a uloží se do cache. Pokud ikona neexistuje, uloží se do cache prázdný soubor. Pokud už soubor v cache uložen je, tak se ikona znovu nestahuje. Při vypisování diskusních příspěvků se odkazy na autorovy stránky (na rozdíl od odkazů přímo v příspěvku) vypisují s atributem rel="nofollow", aby nemátly vyhledávače.
Na závěr přináším seznam deseti nejaktivnějších diskutérů na těchto stránkách:
| Autor | Počet příspěvků |
|---|---|
| Jakub Vrána | 609 |
| dgx | 167 |
| spaze | 108 |
| llook | 64 |
| Jakub Podhorský | 51 |
| Lukas | 50 |
| Leo | 42 |
| Michal | 31 |
| @ss@ssIn | 31 |
| Llaik | 28 |
| Celkem | 3258 |
U nejaktivnějších snadno identifikovatelných autorů jsem URL zpětně doplnil. Pokud jste v minulosti na těchto stránkách aktivně diskutovali a máte zájem o totéž, zanechte komentář u tohoto článku.