Logo du site un pigeon rissa assie sur un caillou pianontant sur un ordinateur dans le noirLogo du site un pigeon rissa assie sur un caillou pianontant sur un ordinateurLibérer les connaissances

Trop de compression, tue la compression. (Image seulement)

Categories:
  • WebP
  • AVIF
  • Zopfli
  • Gzip
  • brotli
  • Comparaison
Tags:

Attention:Cet article est en cours de création et/ou abandonnée. Il est possible qu’il manque des images, qu’il s’arrête en plein milieu d’une phrase. Cela veut dire également qu’il n’a même pas eu le droit à une relecture pour les fautes de français.
Il est soit encore en cours de modification pour qu’il soit terminé un jour ou soit a été abandonnée lâchement dans une forêt par son créateur.
Il est diffusé pour ne pas avoir gâché du temps pour rien, mais personne ne vous demande de vous infliger ça. (s’il s’agit d’une nouvelle méthode de torture, je m’en excuse par avance.)

Dans cet article, je vais vous montrer l’art de la compression sur internet. J’ai comparé plusieurs technologies pour trouver la plus efficace pour une utilisation active sur internet.
baiting: Le résultat est plutôt inattendu et ne correspond pas à l’idée reçue récent = meilleur.

I- La compression, c’est quoi

Même si vous savez tous globalement de quoi il en retourne ; 7zip, Winzip, Winrar, il est important de rappeler la définition pour connaître l’efficacité d’une compression.
La compression est l’art de réduire la quantité d’informations au niveau micro, sans perdre l’information au niveau macro.

Perdre l’information ≠ de dénaturer l’information.

Cette donnée est d’autant plus importante lorsqu’il s’agit d’une image, car un encodage de mauvaise qualité peut la dénaturer de façon très importante (voire outrancière dans certains cas), mais pour autant nous n’aurons pas perdu l’image au sens strict du terme.
Par exemple, avec le jpeg qui suit, nous avons le jpeg original sortit de l’appareil photo (smartphone) et la même image ré-encoder en jpeg qualité 5 :
Photo de mon chat - Original Photo de mon chat - Original
Comme vous pouvez le voir c’est toujours la même image et toujours la même information qui a été compressé (/Ré-encodé).

Certains me diront que l’encodage et la compression est 2 trucs totalement différents et ils auront raison. Pour 2 raisons :

Mais je vais m’abstenir de faire cette différence durant cet article, et je considérerais les encodages d’image comme de la compression avec perte (et encore, on verra plus loin que ce n’est pas le cas)

Je vais également tester les technologies de compression de donnée abstraite. Dans le sens que c’est algorithme ne sont pas spécialisés pour les images.
Par exemple, un dégradé peut-être marqué comme tel pour les encodeurs spécialiser dans les images, car ils savent regarder l’image dans sa globalité et sait déduire le comportement de la donnée à intervalle régulier (un pixel).
Pour une compression abstraite, la plupart du temps elle se base uniquement sur de la répétition de donnée (bits ou octet) qui sont stockés dans un dictionnaire. Pour le coup du dégradé, la compression abstraite sera PARTICULIÈREMENT inutiles car même s’il s’agit un dégradé linéaire de bleu (par exemple) il y aura pas 2 fois exactement le même bleu par exemple. (bon j’exagère, car les pixels de bleu contienne des informations RGB qui peuvent se répéter, mais vous avez compris le fonds de ma pensée)

Bon on va tester quoi !!!!

Les encodeurs WebP et AVIF, les compresseurs Zopfli (Gzip) et Brotli.

Cet article se situe dans une situation d’optimisation de la donnée pour un site web.
Cela veut dire que l’on peut prendre des technologies que le client peut utiliser. Les technologies tel que le 7Zip n’existe pas sur les navigateurs web, ce qui rend leur test inutile/débile.

C’est 4 technologies sont les 4 seuls utilisables (pour les images) sur le web.

En parlant du client…. Est-ce que ce serait pas un c*****d ?

Non bon désolé je suis un peu insultant, pardon de parler comme un charretier.
Mais nous sommes sur le web et sur internet. Le principe même du fonctionnement de l’internet est le commun accord des technologies/langages/encodages/protocoles utilisé entre les 2 systèmes. Cela nous oblige à soit laisser une rétro-compatibilité avec des clients qui ne veulent/peuvent pas utiliser de nouvelle technologie ou sacrifier (sur l’autel des GAFAM) des clients n’accepterons pas les technologies utilisées.

Je vous conseille de laisser une rétro-compatibilité, car il est aujourd’hui très simple de garder une compatibilité avec 100 % des clients sans devoir sacrifier de trop grande performance. Cette phrase n’est valable uniquement au niveau du langage HTML, couche 7 du modèle OSI. Ne me faites pas dire ce que j’ai pas dis pour les couches 4 ou 5, genre le TLS par exemple.

Mais au fait le serveur…. Est-ce que ce serait pas un e*****e ?

Alors oui, je vous vois bien les Webmestres et les administrateurs système au fond de la salle, en train d’insulter les utilisateurs qui mettent pas à jour leur système d’information. Mais circonstanciellement, il y a plutôt de TRÈS GROSSE lacune côté serveur, avec les technologies que l’on doit implémenter nous-mêmes alors que les utilisateurs sont compatibles depuis de très nombreuses années. Du coup, vous aurez beaucoup plus de travail en tant qu’admin sys, plutôt que d’attendre que les utilisateurs soit compatible pour enlever la rétro-compatibilité.

Du coup, la compatibilité….

Ces 4 technologies à une compatibilité qui est très bonne côté client, comme je disais. À l’heure d’écriture de ces lignes nous avons plus de 90 % pour Brotli et WebP, au niveau mondial !!!!! Mais cela explose au niveau européen.
Vous pouvez regarder la compatibilité au niveau mondial, mais il y a très peu de chance que vous ayez un site qui soit destiné au monde entier.

Je suis Français, je suis au centre de l’Europe avec des pays francophones autour de moi. Je vais regarder la comptabilité au niveau européen. Si des Canadiens (Francophone) souhaite accéder à mon blog et bien soit. Mais ils devront avoir la même compatibilité technologique que l’Europe. Si ce n’est pas le cas (dans mon cas), je suis prêt à sacrifier le peu de visibilité outre-Atlantique qui ne serait pas compatible.

A date :

N.B. Certains auront remarqué que je parle de compatibilité Gzip alors bien avant je parlais de compression Zopfli.
Zopfli est en réalité un système de compression de type deflate (comme Gzip), créer par Google. Par conséquent il utilise la même structure que Gzip. Il est donc compatible avec tous les clients qui sont compatibles Gzip.
Il est intéressant uniquement dans des compressions statiques et pas à la volée. Il est beaucoup plus long à compresser que Gzip, mais également plus efficaces, ce qui en fait un très bon candidat pour des sites statiques.

Déploiement des outils

WebP, Gzip

Bon ba c’est le plus simple : vous faites un apt install (ou votre installateur de paquet) pour WebP et Zopfli.
pour le teste j’ai les versions suivantes :
cwebp 0.6.1 -> sur Debian stable (buster 10.10)
Zopfli 1.0.2 -> sur Debian stable (buster 10.10)

Tous les clients et tous les serveurs sont compatibles (ou presque)
Donc vous avez juste à déployer sur votre site. Je vous expliquerai pour chaque techno à la fin de l’article.

Brotli

Vous pouvez installer simplement Brotli avec votre installateur de paquet préféré.
cependant, Brotli n’est pas activé par défaut avec apache et pour nginx il faut recompiler le logiciel pour une prise en charge de Brotli.

Pour apache : sudo a2enmod Brotli
Pour nginx : Voici les commandes à effectuer pour recompiler nginx

apt-get update #Mettez à jour la liste des paquets
apt-get install -y nginx-extras #Installer nginx-extras pour les dépendances
apt-get build-dep -y nginx #Installer les logiciels nécessaires pour la compilation de nginx
mkdir /usr/src/nginx # Création d’un dossier pour les sources
cd /usr/src/nginx && apt-get source nginx # On télécharge les source dans nginx
apt install -y libbrotli-dev brotli git # On télécharge Brotli et ces librairies pour la compilation
git clone https://github.com/google/ngx_brotli /tmp/ngx_brotli # On télécharge les source de Brotli pour nginx
VERSION_NGINX=`apt-cache show nginx-extras/buster | grep Version | awk '{split($0,a);print a[2]}' | awk '{split($0,a,"-"); print a[1]}'` # On récupère la version de nginx(de manière automatique)
sed -i -e 's#^extras_configure_flags.*#extras_configure_flags := --add-module=/tmp/ngx_brotli \\#' "/usr/src/nginx/nginx-$VERSION_NGINX/debian/rules" #On rajoute dans le fichier de config nginx
cd /usr/src/nginx/nginx-$VERSION_NGINX/ #On va dans le dossier des sources pour la compilation
dpkg-buildpackage -b # On compile
cd .. && dpkg -i nginx-common_*.deb libnginx-mod*.deb nginx-extras*.deb #Vous installez les paquets nouvellement compiler.

Congratulation, vous avez nginx de compiler pour brotli. Vous avez également le logiciel brotli en standalone pour compresser les ressources en dehors de nginx.

AVIF

Et là, c’est le drame… Si vous trouviez que cela était beaucoup trop simple, j’ai le bonheur de vous annoncez que cela va complètement changer.
AVIF n’a pas de logiciel compatible sur debian stable (buster) pour encoder ou décoder. Encore mieux, le logiciel sur debian testing, avifenc qui est le logiciel qui normalement permet d’encoder, permet UNIQUEMENT de décoder, car les encodeurs n’ont pas été compilés avec le logiciel…. Nice ^^
De plus, pour bien enfoncez le clou, vous ne pouvez pas utiliser debian stable, car il manque des dépendances je crois, et lorsque vous compiler avec debian testing, il prend une version de LIBC bien supérieur à debian stable et par conséquent vous devrez utiliser un debian testing pour utiliser avifenc.

Pour cela je n’ai aucunement l’intention d’installer une debian testing sur mon ordi, j’utilise simplement une image docker.
Docker était déjà installé sur mon ordinateur, mais si ce n’est pas le cas pour vous je vous conseille plutôt d’installer podman pour les containers.

J’ai créé un Dockerfile qui compile avifenc avec tous les décodeur et encodeur présent sur ce github : https://github.com/AOMediaCodec/libavif.git

FROM debian:testing-slim
#Installation des utilitaires de compilation
RUN bash -c "apt-get update && apt-get install -y build-essential clang nasm git python3-pip curl cmake ninja-build pkg-config openssl libssl-dev libpng-dev libjpeg-dev \
    && pip3 --disable-pip-version-check install setuptools \
    && pip3 --disable-pip-version-check install meson \
    && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && source $HOME/.cargo/env"
#Telechargement de libavif et execution des scripts de téléchargement de dépendance
RUN bash -c "source $HOME/.cargo/env && mkdir -p /opt/src/libavif/ && cd /opt/src/libavif/ \
    && git clone --depth=50 https://github.com/AOMediaCodec/libavif.git /opt/src/libavif/ \
    && git submodule update --init --recursive \
    && cd /opt/src/libavif/ext/ && bash aom.cmd && bash dav1d.cmd && bash libgav1.cmd && bash rav1e.cmd && bash svt.cmd && bash libyuv.cmd"

# La build elle-même (en static)
RUN bash -c "source $HOME/.cargo/env && mkdir /opt/src/libavif/build/ && cd /opt/src/libavif/build && cmake -G Ninja -DCMAKE_BUILD_TYPE=$config -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=ON -DAVIF_LOCAL_AOM=ON -DAVIF_CODEC_DAV1D=ON -DAVIF_LOCAL_DAV1D=ON -DAVIF_CODEC_RAV1E=ON -DAVIF_LOCAL_RAV1E=ON -DAVIF_CODEC_LIBGAV1=ON -DAVIF_LOCAL_LIBGAV1=ON -DAVIF_CODEC_SVT=ON -DAVIF_LOCAL_SVT=ON -DAVIF_LOCAL_LIBYUV=ON -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON .."
# On crée les liens symboliques
RUN bash -c "source $HOME/.cargo/env && cd /opt/src/libavif/build && ninja"

Avec ce dockerfile, vous aurez votre avifenc à l'adresse suivante: /opt/src/libavif/build/avifenc
Il faudrat malgré tout faire fonctionner avifenc dans une image debian testing. Vous cela, vous pouvez simplement utiliser la commande docker run -it <id image docker> bash

Hypothèses et test

Théoriquement, que va-t-il se passer ?

Normalement les encodages sont plus efficaces quand ils sont récents d’après ce qui est dit ici et là par Netflix ou Google.
Ce qu’il faudra tester est l’efficacité :
JPEG/PNG < WebP < AVIF

Pour les compresseurs Zopfli et Brotli, ils ne seront pas aussi efficaces que les encodeurs, voir même ils ne pourront pas compresser + que les encodeurs on pût le faire.
Donc normalement pour la compression, se sera également Sans < Zopfli(Gzip) < Brotli.

SAUF que pour le test, je vais justement compresser les images après qu'elle est été ré-encoder.

ce qui donne :
JPEG/PNG|sans compression < JPEG/PNG|Zopfli < JPEG/PNG|Brotli < WebP|sans compression < WebP|Zopfli < WebP|Brotli < AVIF|sans compression < AVIF|Zopfli < AVIF|Brotli

MAIS CES PAS FINIS !!! Je vais également faire 2 tests pour chaque encodeur différent : pour WebP et AVIF, je vais leur faire tester avec et sans perte (lossy et lossless) ce qui signifie que normalement la compression avec perte serat toujours meilleur que celle sans perte, car la lossless implique une contrainte très importante.

Ce qui nous donne:
JPEG/PNG|sans compression < JPEG/PNG|Zopfli < JPEG/PNG|Brotli < WebP lossless|sans compression < WebP lossless|Zopfli < WebP lossless|Brotli < WebP|sans compression < WebP|Zopfli < WebP|Brotli < AVIF lossless|sans compression < AVIF lossless|Zopfli < AVIF lossless|Brotli < AVIF|sans compression < AVIF|Zopfli < AVIF|Brotli

VOILA !!!! Paye ton tableau avec ce genre de test !!!

Qu’est qui va être testé ?

Je vais tester uniquement les images actuellement issues de mon blog. Ce n’est pas représentatif et je re-ferai peut-être d’autre test si j’en ai la motivation, mais initialement, si j’avais pas eu autant de mal à effectuer c’est test, je n’aurais jamais publié un article là-dessus, et les tests était uniquement dans le but de savoir quel est le meilleur service à offrir aux utilisateurs.

J’ai pris toutes les images de mon blog, ce qui nous donne un total de 67 images dont 14 JPEG et 43 PNG.
La proportion de JPEG et PNG est asymétrique, car je prends beaucoup plus de capture d’écran pour mon blog que de photo et la plupart des images sur internet qui ne sont pas photos, sont des images encodées en PNG. Mais malgré cette asymétrie, je constate bien la différence entre les JPEG et PNG.

Note sur les encodeurs AVIF et WebP

Depuis le début de l’article j’ai fait un abus de langage en mélangeant encodeur et encodage. AVIF et WebP sont des encodages, c’est-à-dire que le logiciel que je vais utiliser va transformer mes fichiers pour les mettre sur c’est standard. Cependant plusieurs logiciels peuvent être utilisés pour arriver à ces standard, ce sont les encodeurs.
Pour WebP, je ne connais pas le nom de l’encodeur. J’utilise le logiciel cwebp et peut-être qu’il n’y a qu’un seul encodeur de webp. Je n’ai donc pas d’encodeur précis, mais voilà.
Pour AVIF, la compilation que je fournis possède de multiple encodeur. Cependant, je n’utiliserai que l’encodeur AOM pour des raisons que j’évoquerai dans les résultats.

Autre information, que j’aurais peut-être dû laisser dans les résultats, car je n’y ai pensé qu’après les tests. Mais WebP et AVIF ne sont pas des encodeurs d’images. Enfin si ce sont des encodeurs d’image mais pas trop non plus.
En réalité, WebP et AVIF sont 2 formats qui découle des encodeurs vidéo qui sont respectivement VP9 et AV1. Alors certe, une vidéo c’est bien une succession d’image accompagnée de son. Cependant vous traiter pas de la même façon une image située dans une vidéo et image seul. Dans une vidéo la plupart des images se ressemblent et à part un travelling agressif, quand vous êtes sur un plan fixe, vous n’avez pas besoin de répéter la même information dans toutes les images qui se succède. C’est pour cela que les encodeurs vont avoir tendance à garder beaucoup d’information au profit d’une potentielle succession d’image dans une vidéo.

Autre note: AOM est le seul encodeur AVIF à faire du lossless.

La qualité

Dans ce test j’ai privilégié une qualité très haute, quitte à prendre beaucoup de temps pour encoder l’image.
Je choisis toujours la meilleure qualité et/ou le traitement le plus lent pour avoir le rapport qualité/poids le plus faible

Le test.

Bon je vais vous notez toutes les commandes que j’ai effectuées pour arriver au résultat final :

### J’ai fait une recherche récursive dans les dossiers du site et j’ai copié+renommé les images avec un nom standard (idem avec png) 
i=1
while IFS= read -d '' -r file; do
    cp $file ~/Bureau/TestImage/IMG$i.jpg
    i=$((i+1))
done < <(find . -follow -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) -print0)
### J'execute les commande d'encodage
find . -maxdepth 1 -type f -exec cwebp -lossless -m 6 '{}' -o './WebP-LossLess/{}.webp' \;
find . -maxdepth 1 -type f -exec cwebp -m 6 '{}' -o './WebP/{}.webp' \;
find . -maxdepth 1 -type f -exec ./avifenc --lossless -s 0 '{}' -o './avif-LossLess/{}.avif' \; #ECHEC; essaie avec -s 0 -> + de 20min. par jpg
find . -maxdepth 1 -type f -exec ../avifenc --jobs all --lossless '{}' -o './avif-LossLess/{}.avif' \;
find . -maxdepth 1 -type f -exec ../avifenc --codec aom --jobs all -s 0 '{}' -o './avif-aom/{}.avif' \;
find . -maxdepth 1 -type f -exec ../avifenc --codec rav1e --jobs all -s 0 '{}' -o './avif-rav1e/{}.avif' \;#ECHEC; + de 30min. par image
find . -maxdepth 1 -type f -exec ../avifenc --codec svt --jobs all -s 0 '{}' -o './avif-svt/{}.avif' \;#ECHEC; + de 30min. par image
### J'execute les commande de compression zopfli et gzip
find . -type f -exec zopfli -v '{}' \;
find . -type f ! -iname "*.gz" -exec brotli -v -q 11  '{}' \;
### Je répertorie les tailles de tous les fichiers dans un fichier csv
while IFS= read -d '' -r file; do
    echo -n "$file;`stat --format="%s" $file`;`stat --format="%s" $file.gz`;`stat --format="%s" $file.br`" >> ~/Bureau/resultTest.csv
    echo -n ";`stat --format="%s" ./WebP-LossLess/$file.webp`;`stat --format="%s" ./WebP-LossLess/$file.webp.gz`;`stat --format="%s" ./WebP-LossLess/$file.webp.br`" >> ~/Bureau/resultTest.csv
    echo -n ";`stat --format="%s" ./WebP/$file.webp`;`stat --format="%s" ./WebP/$file.webp.gz`;`stat --format="%s" ./WebP/$file.webp.br`" >> ~/Bureau/resultTest.csv
    echo -n ";`stat --format="%s" ./avif-LossLess/$file.avif`;`stat --format="%s" ./avif-LossLess/$file.avif.gz`;`stat --format="%s" ./avif-LossLess/$file.avif.br`" >> ~/Bureau/resultTest.csv
    echo ";`stat --format="%s" ./avif-aom/$file.avif`;`stat --format="%s" ./avif-aom/$file.avif.gz`;`stat --format="%s" ./avif-aom/$file.avif.br`" >> ~/Bureau/resultTest.csv
done < <(find . -follow -type f \( -iname "*.jpg" -o -iname "*.png" \) -print0)

Résultat

Tableau des résultats Voici les codes couleurs que j’ai mis en place:
-> Les lignes jaunes sont les JPG.(J’aurais dû faire un autre tableau, je sais. J’avais la flemme.)
-> Les cases vertes signifie que le fichier à une plus petite taille que celui de la case à sa gauche. Si toutes la lignes est verte cela veut dire qu’elle respecte le modèle suivant : JPEG/PNG|sans compression < JPEG/PNG|Zopfli < JPEG/PNG|Brotli < WebP lossless|sans compression < WebP lossless|Zopfli < WebP lossless|Brotli < WebP|sans compression < WebP|Zopfli < WebP|Brotli < AVIF lossless|sans compression < AVIF lossless|Zopfli < AVIF lossless|Brotli < AVIF|sans compression < AVIF|Zopfli < AVIF|Brotli
-> Les cases rouges c’est quand l’encodeur a fourni un fichier plus grand que l’encodeur précédent dans le modèle : JPEG/PNG < WebP lossless < WebP < AVIF lossless < AVIF. Exception pour la colonne des AVIF que je compare à WebP plutôt que AVIF lossless. Pour les raisons que je vais décrire plus tard.

Interprétation

1er phase : les évidences

Ok, je vais pas vous mentir la colonne rouge sur AVIF lossless n’était pas réellement prévu. Et je n’arrive pas à comprendre comment il est possible de tripler la taille des images en faisant du lossless.
Ce qui est magique c’est qu’avec cet encodeur, nous créons de l’information !!!!! Je trouve ça miraculeux !!!!!! Rendez-vous compte, nous ne sommes pas à simplement dire il a pris l’images et à juste modifier un peu l’encodage pour être compatible avec le format AVIF. NON !!! Il a multiplié les informations sur chaque pixel comme des petits pains.

Vous pouvez prendre n’importe quel gif de cette page : https://giphy.com/search/what qui montre mon état d’esprit
--------
Le deuxième constat que l’on peut faire du 1er coups d’œil, c’est la différence JPEG/PNG.
Ils ont un comportement totalement différent avec chacun des paramètres.
On peut déjà dire que l’on ne peut pas utiliser WebP lossless sur les jpeg. Tous comme AVIF lossless, il arrive à « créer de l’information ».
Mais WebP lossy est très efficace sur les JPEG. Il est donc fortement recommandé de l’utiliser

2ᵉ phase : Regardons les chiffres et leur delta.

Resultat en delta
Pour ce tableau j’ai fait la différence en octet de la case en cours avec celle de gauche. Normalement, si le modèle était parfait, il ne devrait pas y avoir un seul nombre négatif dans le tableau.

Mais J’ai constaté un autre truc : les delta des colonnes brotli sont faibles, voir très faible et extrêmement homogènes pour WebP et AVIF. Mais encore pire, ils ont un fort delta négatif pour les originaux et pour WebP lossless… Dans ce cas-là, il ne crée pas de donnée, mais brotli est extrêmement moins performant de Zopfli… Quelle que soit la situation, Brotli est totalement inefficace pour les images… D’après quelque lecture ici et là, cela s’explique par le fait qu’il a été créé dans le but de compresser du texte et non des images. Il n’est probablement efficace uniquement pour les fichiers html/css/js.

Zopfli devient de moins en moins efficace au fur et à mesure de la qualité de compression des encodages. Ce qui est logique, les encodages sont des formes de compression optimisé pour les images, il y a très peu de possibilité de compression après le passage d’encodeur qui ont déjà effectué la plupart des opérations faisable par Gzip.
Rien que à partir de WebP lossless, nous avons une moyenne de 167 octets de gagner par compression Zopfli. Ce qui n’est pas spécialement rentable, même si cela ne peut pas faire de mal. 588 octets (de moyenne) pour WebP et 135 octets (de moyenne) pour AVIF


Licence Creative Commons
Trop de compression, tue la compression. (Image seulement) de Clément Cachinho est mis à disposition selon les termes de la licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International.
Fondé(e) sur une œuvre à https://blog.noknow.ovh/article/Art-Compression-Images.html.