De nos jours les images sont de plus en plus grandes et par conséquent lourdes. Si l’on ajoute à ça les écrans haute densité (Retina), on peut vite plomber les performances d’un site web.

La plupart des images sont au format JPEG, qui est beaucoup trop vieux et plus vraiment adapté aux besoins d’ajourd’hui. Google propose un nouveau format avec le WebP mais ça ne fait pas l’unanimité et seul Chrome le supporte, donc l’alternative ne semble pas viable pour le moment.

Mais quand il s’agit de compression, rien ne bat un codec vidéo, donc pourquoi ne pas essayer d’encoder une image en une vidéo ne contenant qu’une frame ?

Comme image de base on va utiliser un PNG de 1920x1080, comme en ce moment il pleut j’ai pris une image en rapport :

1920x1080 - png - 2.7Mb
1920x1080 - png - 2.7Mb

Ensuite on va l’encoder en JPEG à 70%, ce qui est très commun pour une image sur le web.

1920x1080 - jpeg 70% - 507Kb
1920x1080 - jpeg 70% - 507Kb

L’image est plus de 5x plus petite que l’originale ce qui est bien, mais bon 507Kb c’est encore beaucoup, surtout pour des appareils mobiles.
Mais on peut aller un peu plus loin avec le vénérable JPEG en utilisant des utilitaires de compression, comme par exemple mozjpeg.

jpegtran -copy none -optimize -progressive -outfile opt.jpg img.jpg

1920x1080 - jpeg 70%+ mozjpeg - 501Kb
1920x1080 - jpeg 70%+ mozjpeg - 501Kb

Pas fameux, on a gagné environ 1,1%. Après on peut utiliser JPEGmini qui est destructif contrairement à ce qui est annoncé, mais ça ne se voit pas trop et c’est plutôt efficace, problème majeur, c’est payant.

1920x1080 - jpeg 70% + JPEGmini - 309Kb
1920x1080 - jpeg 70% + JPEGmini - 309Kb

L’image résultante est 1,6x plus petite que précédemment, on peut donc dire que le gain est très intéressant, mais nous sommes arrivés au maximum de ce que le JPEG nous propose.

Il est donc temps de regarder du côté des codecs vidéo, problème c’est la jungle (le web quoi…) et en fonction du navigateur il va falloir encoder différemment. Internet Eplorer, Safari, Chrome peuvent lire le H.264, pour Firefox il va falloir du VP8, Chrome le gère aussi vu que Google supervise son développement.

Pour réaliser ça on va avoir besoin du couteau suisse de l’encodage vidéo, à savoir ffmpeg et de x264.

Première étape, convertir notre image originale en un format qui sera compris par l’encodeur :

ffmpeg -i img.png -y -pix_fmt yuv420p img.y4m

Ensuite on va commencer par celle au format H.264 :

x264 --frames 1 --8x8dct --profile high --level 4.1 --trellis 2 --subme 11 --psy-rd 1.5:0.5 --aq-strength 1.2 --deblock -2:-2 --tune stillimage --qcomp 0.5 --bitrate 2500 -o img.mp4 img.y4m

Le fichier résultant est un mp4, j’ai choisi le bitrate au pif pour avoir une image de qualité similaire au JPEG à 70%. Les plus curieux peuvent jouer avec les paramètres, y a moyen de gagner encore en taille.

Pour le fichier WebM :

ffmpeg -i img.y4m -y img.webm

Les scores par rapport au JPEG sont sans appel :

  • H.264 : 132Kb, soit 3,8x plus petit que le JPEG à 70% et 2,3x que JPEGmini.
  • VP8 : 38Kb, soit 13,3x plus petit que le JPEG à 70% et 8,1x que JPEGmini.

Même en additionnant la taille des deux vidéos on est toujours à un poids nettement inférieur à JPEGmini.

Conclusion

Vous pouvez la faire vous même, vous êtes assez grand non?

PS: Le temps s’est dégagé donc mon image n’est plus d’actualité, je suis dégoûté.