PROJET AUTOBLOG


Tiger-222

Archivé

Site original : Tiger-222

⇐ retour index

TrueCrypt : entretien avec Ennead

samedi 26 octobre 2013 à 21:33
Ce qui suit est une traduction libre de l'entretien d'un des développeurs du logiciel TrueCrypt, Ennead, par WolfManz611. C'était le samedi 10 septembre 2005.

Entetien rare avec Ennead, un des développeurs de TrueCrypt


WolfManz611 : Quel est ton rôle au sein du projet TrueCrypt ?
Ennead : J'ai 29 ans et plusieurs casquettes dans ce projet : administrateur, développeur et designer. Je suis aussi responsable de la documentation et du site web.

WolfManz611 : Combien de temps as-tu passé sur le projet pour en arriver au stade où il est, et combien de développeurs travaillent dessus ?
Ennead : Actuellement, il y a deux développeurs principaux (aussi administrateurs) qui travaillent sur TrueCrypt. Quant à savoir combien de temps nous avons passé sur sur le projet, je dirais beaucoup. Nous avons l'habitude de faire une courte pause après chaque version majeure (à moins qu'il y ait un bogue majeur qui requiert d'être résolu immédiatement) puis commençons à travailler sur la prochaine version. Une partie considérable de notre temps est consacrée à ce projet.

WolfManz611 : À quels types d'utilisateurs ce programme est-il destiné ?
Ennead : C'est une bonne question. Nous essayons constamment d'équilibrer les choses. D'un côté, vous avez les utilisateurs inexpérimentés qui requièrent une prise en main facilitée au maximum, et de l'autre, vous avez les power users qui, quelques fois, demandent des fonctionnalités vraiment obscures, ce qui peut effrayer le communs des mortels. Ce que nous essayons de faire, c'est de trouver le bon compromis qui satisfasse les deux partis.

En outre, il existe des problèmes mono-utilisateur (maison) vs. multi-utilisateurs (société) . Par exemple, les sociétés nous demandent d'implémenter des "portes dérobées" [NdT : backdoors] dans le cas où un employé oublie son mot de passe, etc. À cet égard, notre logiciel s'adresse plus à des utilisateurs individuels. Malgré cela, d'après les courriels que nous recevons, nous savons qu'il y a beaucoup de sociétés et d'organismes gouvernementaux qui utilisent TrueCrypt.

WolfManz611 : Est-ce que ce programme prend quelconque contre-mesure pour déjouer les keyloggers ?
Ennead : Actuellement, TrueCrypt n'offre aucune protection active contre les logiciels malveillants. Nous pensons que c'est le rôle du logiciel anti-virus. Pour les keyloggers, la meilleure solution pour les contrer est l'utilisation des fichiers de clef [NdT : keyfiles]. Nous avons déjà implémenté le support des fichiers de clef et une nouvelle version devrait voir le jour d'ici peu.

WolfManz611 : Pour donner une idée : en assumant que l'utilisateur ait un mot de passe de 20 caractères aléatoires, à quel point le chiffrement est-il bon en utilisant le type de chiffrement par défaut ? Combien de temps prendrait une tentative de cassage du chiffrement en utilisant une pièce remplie d'ordinateurs haut de gamme ?
Ennead : Je n'ai pas la réponse précise mais je peux donner une estimation. 20 caractères choisis aléatoirement équivaut, en gros, à une clef 128 bit. Disons q'un ordinateur haut de gamme soit capable de tester 100 mots de passes TrueCrypt par seconde. Si nous liions 10 000 ordinateurs de ce même type ensemble, nous pourrions tester 1 000 000 mots de passe par seconde. Par conséquent, il faudrait 5 395 141 535 403 007 094 485 264 années, en moyenne, pour trouver le mot de passe.

Notez que l'estimation ci-dessus n'est valable que si le mot de passe est vraiment aléatoire. S'il s'agit de mots trouvés dans un dictionnaire, noms d'animaux de compagnie, dates d'anniversaire, numéros de téléphone et ainsi de suite, ça pourrait prendre moins de temps pour trouver le mot de passe (l'attaque par force brute peut être optimisée). Il est très important de choisir un bon mot de passe.

WolfManz611 : J'ai remarqué que tu peux enregistrer les mots de passe dans le pilote mémoire. Pourquoi les enregistrer là par opposition à la mémoire normale ?
Ennead : Une des raisons est qu'il fallait permettre la mise en cache du mot de passe même quand l'application TrueCrypt se ferme. Le pilote est indépendant de l'application TrueCrypt.

WolfManz611 : Après un redémarrage ou la mise hors tension de l'ordinateur, le mot de passe dans le pilote mémoire est-il retenu ?
Ennead : Non, le pilote TrueCrypt est arrêté en même temps que Windows.

WolfManz611 : Penses-tu que plus de programmes actuels, comme les clients de messagerie électronique et similaires, devraient utiliser une sorte de chiffrement sur leurs paramètres et tous les messages qu'ils gèrent ?
Ennead : Oui, bien sûr. De plus en plus de personnes commencent à comprendre que leur vie privée [NdT : vie intime] est quelque chose qu'ils devraient protéger. Si votre client de messagerie ne supporte pas le chiffrement, il devrait au moins vous permettre de le configurer de telle sorte que tous les fichiers sensibles sur lesquels vous travaillez soient stockés dans un volume TrueCrypt (c-à-d chiffrés à la volée).


WolfManz611 : Quel est le minimum requis pour que ton programme fonctionne correctement ?
Ennead : Je ne pense pas que TrueCrypt soit très exigeant à cet égard. Il requiert seulement quelques mégaoctets de mémoire vive et environ un mégaoctet d'espace disque.

WolfManz611 : Avec la recrudescence des vols de données personnelles, ne penses-tu pas que la majorité des gens devrait utiliser un programme comme TrueCrypt afin de tenir les voleurs éloignés ?
Ennead : Eh bien, si le système d'exploitation est infecté, TrueCrypt n'empêchera pas les voleurs d'accéder aux données si un volume TrueCrypt est monté. L'utilisation d'un anti-virus décent est définitivement recommandée.

WolfManz611 : Travailler sur une version Linux et, si oui, où est-ce que ça en est ? Sera t-elle équivalente à celle de Windows ou meilleure ?
Ennead : Oui, pendant que je travaille sur la version Windows, Syncon fini le travail de la version Linux. Elle était en phase alpha pendant plusieurs semaines et semble très stable.

Initialement, les deux versions ne seront pas égales. Par exemple, il n'y aura pas de GUI pour la version Linux. Cependant, dans un futur proche, les deux versions devraient être équivalentes.

WolfManz611 : Quelle est la cote de popularité du programme et, à ton avis, combien de personnes l'utiltisent ou l'ont téléchargé ?
Ennead : D'après les statistiques de SourceForge.net et des log du serveur, à peu près un quart de million de personnes ont téléchargé TrueCrypt 3.1a. Il y a aussi beaucoup d'entités, comme le magazine Chip, qui hébergent nos fichiers sur leurs serveurs, ce qui rend l'estimation impossible.

WolfManz611 : Dans quel langage de programmation est-il codé ?
Ennead : Le code source est entièrement écrit en C, hormis les routines de l'algorithme de chiffrement Serpent, qui est en assembleur. Vu que notre objectif est de rendre le code multi-plateforme, nous prévoyons de remplacer le code assembleur par du C.

WolfManz611 : Prévoyez-vous d'implémanter de grosses fonctionnalités et, si oui, quelles sont-elles ?
Ennead : Oui, c'est prévu. Mais ça ne serait plus une surprise si je te le disais !

WolfManz611 : Quelle est la problématique du fichier d'échange de Windows pour ce genre de programme ? Est-ce que le fichier d'échange de Windows entre en jeu seulement pour écrire un fichier dans le volume chiffré ou compromet-il les fichiers même lors de la lecture de ceux-ci depuis un volume chiffré ?
Ennead : Chaque fois que vous ouvrez un fichier stocké sur un volume TrueCrypt dans un programme (par exemple, dans un éditeur de texte), une partie du fichier est déchiffré dans la RAM et transmise au programme qui les a demandées. TrueCrypt utilise une réserve [NdT : pool] non-paginée pour stocker les mots de passe en cache, les clefs de chiffrement, IVs et autres données sensibles relatives au volume, donc ces données ne peuvent pas être divulguées au fichiers de pagination. Cependant, TrueCrypt ne peux prévenir l'accès au contenu déchiffré des fichiers sensibles ouverts en mémoire. Par conséquent, nous recommandons fortement aux utilisateurs de désactiver le fichier d'échange 1 , au moins pour chaque session durant laquelle ils travaillent avec des données sensibles.

WolfManz611 : Prévois-tu de faire d'autres projets qui impliquent le chiffrement, comme un module de client de messagerie facile à utiliser ?
Ennead : En ce qui concerne le logiciel de chiffrement, nous allons probablement rester avec le modèle de chiffrement de disque à la volée, que nous considérons comme le plus efficace.

WolfManz611 : Que fait SourceForge.net pour votre programme ? Est-ce qu'il vous donne une bonne exposition et plein de téléchargements ?
Ennead : Eh bien, j'estime qu'environ 5% des utilisateurs de TrueCrypt l'ont découvert via SourceForge.net. Globalement, les services de SourceForge sont bons, mais il y a des choses qui peuvent être améliorées. Par exemple, la sécurité des services web et les performances des serveurs MySQL sont les raisons pour lesquelles nous avons décidé de migrer le site et les forums sur notre propre serveur dédié.


1 -- Désactiver le fichier de pagination sous Windows. Pour GNU/Linux :
# swapoff partition
sudo swapoff /dev/sda1

Déployez vos modules Python

mardi 22 octobre 2013 à 11:30
Python ou pas, il est vert !

Vous venez de terminer votre nouveau module Python ! Évidemment, vous l'avez testé dans tous les sens, et souhaitez le déployer vite fait, bien fait. Un module aisément installable, quelque soit le système d'exploitation, est appréciable pour tout le monde ☺

C'est là qu'entre en jeu pip. Je ne rentrerai pas dans les détails du fonctionnement de pip, d'autres les font très bien. Je m'attarderai plutôt sur la création des fichiers nécessaires ainsi que l'envoi au serveur.
Pour les pressés, voici un mémo des commandes :
$ python setup.py register
$ python setup.py sdist upload


Préparer la base


Vous avez sûrement déjà vu un de ces fameux setup.py, et bien c'est lui qui gère tout. Vous pouvez voir les projets MSS ou minibelt pour vous en inspirer ; voici un exemple tiré du module MSS :
# Import du bon module de gestion
try:
from distutils.core import setup
except ImportError:
from setuptools import setup

# Dans le fichier MANIFEST.in, on y liste les ficihers et dossiers à inclure (ou pas)
# dans l'archive qui sera déployée.
# Par défaut, seuls les fichiers module.py et setup.py sont inclus.
open('MANIFEST.in', 'w').write('\n'.join((
"include *.rst",
# un_dossier/*.py
# un_autre_fichier.py
# prune archives/ <-- ne pas inclure le dossier archives
)))

# En option, importez la version de votre module
from mss import __version__

# Le nom des clefs est assez explicite, on renseigne les infos principales du module
setup(
name='mss',
version=__version__,
author='Tiger-222',
py_modules=['mss'],
author_email='contact@tiger-222.fr',
description='A cross-platform multi-screen shot module in pure python using ctypes',
long_description=open('README.rst').read(),
classifiers=[
'Programming Language :: Python',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'License :: OSI Approved :: zlib/libpng License',
'Natural Language :: English',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Topic :: Multimedia :: Graphics :: Capture :: Screen Capture',
],
url='https://github.com/BoboTiG/python-mss'
)
Vous aurez remarquer la présence d'un certain README.rst (format ReStructuredText), il s'agit de la description complète du module (ses classes et méthodes, exemples, ...).
La liste des classifiers se trouve ici : List trove classifiers.

En passant, GitHub accepte les fichiers README.rst, pratique ! Et voici une visionneuse de fichiers RST : restview.


Le déploiement


Créer le dépôt


Ouvrez une console, rendez-vous dans le répertoire du projet, puis :
$ python setup.py register
running register
running check
We need to know who you are, so please choose either:
1. use your existing login,
2. register as a new user,
3. have the server generate a new password for you (and email it to you), or
4. quit
Your selection [default 1]:
Si vous n'avez pas encore de compte, prenez l'option 2, sinon la 1.

Si tout s'est bien passé, vous devriez avoir ce genre de message :
Registering mss to http://pypi.python.org/pypi
Server response (200): OK

Voilà, votre module est en ligne !


Envoyer le module


La page du module a été créée, mais aucun fichier n'est disponible en téléchargement. Cette commande génère une archive puis l'envoie au serveur :
$ python setup.py sdist upload
running sdist
running check
warning: sdist: standard file not found: should have one of README, README.txt

reading manifest template 'MANIFEST.in'
writing manifest file 'MANIFEST'
creating mss-0.0.2
making hard links in mss-0.0.2...
hard linking README.rst -> mss-0.0.2
hard linking mss.py -> mss-0.0.2
hard linking setup.py -> mss-0.0.2
creating dist
Creating tar archive
removing 'mss-0.0.2' (and everything under it)
Submitting dist/mss-0.0.2.tar.gz to http://pypi.python.org/pypi
Upload (200): OK
Emballé, c'est pesé !

Vous pouvez de suite installer le module fraîchement déployé : pip install mss !


Sources

PHP : is_file vs file_exists

lundi 14 octobre 2013 à 17:32
is_file, comme la documentation l'indique, vérifie si le fichier est un véritable fichier, tandis que file_exists vérifie si un fichier ou un dossier existe. À savoir que ces deux fonctions utilisent un système de cache, elles partent donc sur un pied d'égalité.

Les sources


Rien de mieux que le retour aux sources pour voir les entrailles de ces deux fonctions. Il s'avère qu'elles utilisent la même function en interne, seules les routines de vérification diffèrent.

Ci-dessous, le pseudo code très simplifié du processus de vérification :
function php_stat($fichier)
{
'file_exists'
↳ virtual_file_ex($fichier)
↳ virtual_access($fichier)
'Windows'
↳ tsrm_win32_access($fichier)
↳ return access($fichier)
'Autres systèmes'
↳ return access($fichier)
↳ return _php_stream_stat_path($fichier) == FALSE
'is_file'
↳ _php_stream_stat_path($fichier)
↳ return $fichier.st_mode == S_IFREG
}

Pour les curieux, voici les sources des fonctions :
Au premier abor, ça semble clair comme de l'eau de roche, file_exists() nécessite bien plus d'opérations à effectuer. Cependant, _php_stream_stat_path() est lourde puisqu'elle récupère toutes les informations sur un fichier/dossier (appelé inode) : volume, numéro d'inode, droit d'accès à l'inode, nombre de liens, userid du propriétaire, groupid du propriétaire, type du volume, si le volume est une inode, taille en octets, date de dernier accès (Unix timestamp), date de dernière modification (Unix timestamp), date de dernier changement d'inode (Unix timestamp), taille de bloc et le nombre de blocs de 512 octets alloués.

Il faudra attendre de voir le résultat des tests pour se faire une meilleure idée.


Une meilleure alternative ?


Dans ce commentaire, DeyV laisse à penser que stream_resolve_include_path serait une bonne alternative à file_exists(). À priori, cette fonction utiliserait aussi le système de cache.
Great alternative to file_exists() is stream_resolve_include_path() -- DeyV
Toujours d'après les sources, le pseudo code suivant en ressort :
function stream_resolve_include_path($fichier)
{
zend_resolve_path($fichier)
↳ php_resolve_path_for_zend($fichier)
↳ php_resolve_path($fichier)
↳ tsrm_realpath($fichier)
↳ return estrdup($fichier)
}

Pour les curieux, le détail de chaque fonction :
Notez que le fait d'utiliser des chemins absolus permet un gain non négligeable.


Les tests


Configuration de la machine de test


Le benchmark


Deux types de tests : un réaliste où on teste la présence de fichiers différents, et un autre moins parlant dans lequel le même fichier est testé 1 000 000 de fois.
Pour le test réaliste, j'ai créé un dossier test qui contient 1 000 000 fichiers (le premier fichier s'appelant 0 et le dernier 999999).
D'après le script qui permet de lancer et chronométrer les tests, le graphique suivant en résulte :



Observations



Historique


MàJ du 2013-10-23 : ajout des explications avec les sources PHP
MàJ du 2013-10-25 : Une meilleure alternative ?
MàJ du 2013-10-27 : ajout de tests plus réalistes et étoffement des informations
MàJ du 2013-10-28 : ajout du script de tests pour ne pas trop encombrer la page

Shaarlimages reloaded !

vendredi 20 septembre 2013 à 01:57
Shaarlimages.net

Shaarlimages.net a subi des débuts assez chaotiques, j'avoue, mais il faut savoir vivre dans le danger !
Pour vous en mettre plein la vue, jettez un œil à cette image, et utilisez les flèches gauche & droite pour aller à la précendente & suivante... ❤
Bref, suite à de nombreux retours, tous positifs, voici quelques informations.


Changements


Étant donné que la base était assez légère, il n'y a pas grand chose de changé, hormis la couleur de fond de la galerie qui est passée à #EEEEEE.
Le système de la galerie a été entièrement réécrit en JS/CSS/HTML, plus de PHP. Ça permettra d'avoir des galeries sur clefs USB ou des serveurs sans PHP (ça existe encore ?). D'ailleurs, pour ceux qui veulent s'approprier juste le système, reportez-vous au dépôt Galinear (je le mettrai à jour une fois que j'aurai quelque chose de plus facile à intégrer).
MàJ du 2013-09-23 : utilisation de la liste des shaarlis de Shaarli Flux River, plus complète.
MàJ du 2013-09-26 : amélioration notable lors de la récupération des liens et création de thumbnails pour alléger les pages.
MàJ du 2013-09-27 : refonte du code, tout est paramétrable dans inc/Config.php.


Nouveautés


Ou plutôt devrais-je dire : fonctionnalités de base que je n'avais pas encore implémentées...

J'ai mis le paquet sur la possibilité de personnaliser l'affichage. Les paramètres par défaut peuvent être modifiés soit en passant par l'URL, soit en utilisant le petit panneau en haut à gauche, qui utilise les cookies pour que ça soit permanent. Les différents paramètres sont :

Un gros travail a été fait pour rendre le code plus agréable et facile à étudier. Je me suis pas mal inspiré des projets KrISS feed (vraiment propre, c'est du joli !) et Shaarli Flux River (pour la classe RSS).


Futur


Ketluts a proposé d'utiliser un fond ambiligth plutôt qu'une couleur moyenne : je regarderai ça plus tard, ça pourra être une option d'affichage, en tout cas, ça rend bien. (OK, MàJ du 2013-09-28, d'autres informations sur cette page : Ambilight для тэга video)

La prise en compte des évènements de toucher pour les smartphones (faire glisser un doigt pour changer d'image ou de page). (OK, MàJ du 2013-09-26)

Et la mise en place d'une API pour faire toute sorte de recherches.

Sur certains site web, l'accès est difficile. Par exemple pour le Shaarli de Sam Ganegie, j'ai plus souvent cette erreur que le flux : Access denied | sameganegie.biz used CloudFlare to restrict access. Sur celui du Warrior du Dimanche, idem, c'est à la roulette russe, j'ai une restriction comme quoi mon adresse IP est cataloguée en SPAM. Il faut trouver une parade.


Appel de détresse


Avec tous les services qui se font autour de shaarli (Flux RSS des Shaarlis -- 102 liens, Shaarlo -- 105 liens, Shaarli Flux River -- 111 liens et ShaarliTV), il serait fort intéressant d'avoir un seul fichier OPML contenant les différents shaarlis actifs. J'utilise celui de Shaarlo, mais il y a déjà deux flux HS. Ça vous tente de regrouper vos URL vers Shaarlo ? Ou autre part, je ne suis pas casse-pied. ☺

MàJ du 2013-09-26 : mon appel a été entendu ! Voici une 1ère réponse et des idées pour un annuaire de Shaarlis (n'hésitez pas à participer, tous les avis sont bons à prendre).

Shaarlimages.net

jeudi 12 septembre 2013 à 23:23
shaarlimages.jpg

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="./media/00a3687b." data-original-source="https://tiger-222.fr/"><img src="./media/084d514f.image.jpg" data-original-source="https://tiger-222.fr/images/image.jpg"></a>
</figure>

<!-- Un exemple avec une image sensible (NSFW) -->
<figure data="nsfw">
<a href="./media/00a3687b." data-original-source="https://tiger-222.fr/"><img src="./media/df2ddecb.image-trop-sexy.jpg" data-original-source="https://tiger-222.fr/images/image-trop-sexy.jpg"></a>
</figure>
</div>

<script async src="https://tiger-222.fr/linear-partition.min.js"></script>
Pensez aussi à include 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 (qui utilise des images).

É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 ☺