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 <link>
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, https://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, https://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.
Na adrese http://www.google.com/s2/favicons?domain=
běží webová služba pro získávání ikon ve formátu PNG.
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.
Diskuse je zrušena z důvodu spamu.