Aperçu de Shaarlimages.net

Suite à cette requête, je me suis penché sur le sujet. Après quelques recherches et bidouillages de codes, je vous présente Shaarlimages ! Pour l'occasion, j'ai réservé le nom de domaine, mais si quelqu'un d'autre le veut, je pourrai le céder facilement ☺.

Le but était d'avoir une galerie qui soit d'un niveau proche de celle de Chromatic.io. Je me suis imposé de ne pas utiliser de bibliothèques tierces telles que jQuery ou Prototype ; c'est du donc du javascript natif. Les sources de chromatic.io étant relativement obfusquées (quelle merde ce cloud d'Amazon...), je me suis largement inspiré du projet de Jakob Holmelund : fitpicjs, un grand merci à ce brave homme !


La démo

C'est sur Shaarlimages.net que ça se passe. Il est possible de filtrer par date en ajoutant à l'URL le paramètre d : ?d=aaaammdd, exemple avec la journée du 8 août 2013.

Par défaut, si le tag NSFW (Not Safe for Work) est trouvé dans la catégorie, le titre ou la description, l'image sera alors presque invisible. En cliquant dessus, par contre, l'image ne sera pas filtrée. Il est possible de désactiver ce filtrage en passe le paramètre $CONFIG['show_nsfw'] à true.

Je me sers du fichier d'export de shaarli.fr pour récupérer la liste des shaarlis à parser, donc si vous souhaitez ajouter le vôtre, envoyez un p'tit mot.


Téléchargement

Le code du site entier est sur GitHub, faites-vous plaisir !


Plus d'informations ?

La galerie utilise le système de partition linéaire, c'est-à-dire perdre le moins d'espace possible. Les images sont redimensionnées pour qu'une quantité correcte soit affichée par ligne, et ce de façon agréable visuellement ☂. L'article The algorithm for a perfectly balanced photo gallery (en anglais) explique un peu plus en détails le principe.
Lors d'un clic sur une image, l'affichage est important : l'image prend le maximum d'espace sur l'écran et la couleur de fond est adaptée à chacune d'entre elles. J'utilise une fonction PHP pour déterminer la couleur dominante moyenne :

function docolav($fichier) {
    list($width, $height, $type) = getimagesize($fichier);
    if ( $type == 2 ) {  // jpeg
        $img = imagecreatefromjpeg($fichier);
    } elseif ( $type == 3 ) {  // png
        $img = imagecreatefrompng($fichier);
    } else {
        return NULL;
    }
    
    // http://stackoverflow.com/questions/6962814/average-of-rgb-color-of-image
    $tmp_img = ImageCreateTrueColor(1, 1);
    ImageCopyResampled($tmp_img, $img, 0, 0, 0, 0, 1, 1, $width, $height);
    $rgb = ImageColorAt($tmp_img, 0, 0);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b =  $rgb & 0xFF;

    unset($rgb);
    imagedestroy($tmp_img);
    imagedestroy($img);
    return sprintf('%02X%02X%02X', $r, $g, $b);
}

Ce code est relativement rapide (bien plus que ma version C++ d'ailleurs...), on demande à redimensionner l'image à 1x1 pixel, tout en gardant l'échantillonnage des couleurs : donc calcul de la couleur moyenne dominante pour savoir quelle sera la couleur de ce seul pixel. Bien pensé et diablement plus efficace que parcourir tous les pixels à la main.

De plus, si vous avez compris le code, vous aurez requarqué que seuls les formats d'image JPEG et PNG sont pris en compte. D'autres seront à venir suivant la demande (hormis pour les images animées).


Pour les développeurs

Avant tout, sachez que ce n'est pas la mer à boire : 3.2 ko (CSS) + 3.1 ko (JS) = 6.3 ko !

Ensuite, Shaarlimages est un exemple, mais pour ceux qui veulent utiliser le même système ailleurs, voici comment faire. Dans votre code, il faut définir un conteneur avec l'ID image-container. Dans ce conteneur, chaque image doit être encadrée dans une figure. Puis incluez le code javascript en bas de page, ça devrait être bon.

Exemple :

<div id="image-container">
	<figure>
		<a href="?i=image.jpg"><img src="images/image.jpg"></a>
	</figure>

	<!-- Un exemple avec une image sensible (NSFW) -->
	<figure data="nsfw">
		<a href="?i=image-trop-sexy.jpg"><img src="images/image-trop-sexy.jpg"></a>
	</figure>
</div>

<script async src="linear-partition.min.js"></script>

Pensez aussi à inclure le fichier CSS.


Améliorations possibles

Dans l'immédiat, la couleur de fond pour chaque image est calculée (couleur moyenne dominante) et une image est ajoutée par dessus pour le grain. Bien que ça ne rende pas trop mal, il faudrait revoir le mécanisme pour se rapprocher un peu plus de cette galerie.

Éventuellement, trouver un service en ligne, ou un code PHP, permettant de compresser les images (progressif pour le JPEG, et optimisations générales).

Pour le reste, libre à vous de forker, bidouiller et proposer des patches ☺