Optimiser ses images et ses commandes shell

Magazine
Marque
Linux Pratique
Numéro
103
Mois de parution
septembre 2017
Spécialité(s)


Résumé
Des logiciels libres permettent de gagner de la place sur votre disque dur en recompressant vos images JPEG et PNG de 25 % dans le meilleur des cas, et sans perte de qualité ! Puisque ces commandes sont un peu lentes, voyons aussi comment paralléliser le processus sur vos noyaux et accélérer encore l’exécution de chaque commande de 20 % sur votre machine.

Body

J'ai découvert l'été dernier les commandes jpegoptim et zopflipng, elles se proposent chacune de recompresser, sans perte de qualité, des images JPEG et PNG. On peut espérer jusqu'à 25% de gain de place pour les photos (floues et granuleuses) prises (de travers) depuis un smartphone Android (pendant un concert...). Un quart de place, sur le stockage limité de ce genre de périphérique, ça peut être appréciable.

Par contre, s'il s’agit de reprendre toutes ses photos rangées automatiquement dans des dossiers horodatés depuis 15 ans, y'a moyen d'y passer un brave moment, d'autant que ces commandes annoncent la couleur : elles sont lentes, car il faut du temps pour réussir à faire mieux que les encodeurs JPEG et PNG que l'on rencontre généralement…

Voyons comment lancer efficacement ses optimisations d'images, dans un article digne d'un Inception ou d'un Existenz au cinéma, où l'on descendra dans la meta-optimisation du processus, en recompilant entre autres les commandes, pour gagner aussi sur le temps d'exécution.

1. Optimiser les images

jpegoptim est une commande développée depuis 15 ans et présente de longue date dans les dépôts Debian. Elle optimise les tables de Huffman utilisées pour la compression des JPEG en testant différents paramétrages, et garde, pour chaque image, le meilleur résultat. Il est également possible de lui demander une réduction jusqu'à la taille voulue, et l'algorithme fera alors de son mieux avec cette contrainte pour limiter la casse. Pour l'installer :

apt install jpegoptim

zopfli est lui un algorithme de compression relativement récent (le premier commit du dépôt Git du projet date d'il y a 4 ans). La commande zopflipngn'est d'ailleurs pas encore présente dans les dépôts Debian, et il faut aller se la cloner depuis le dépôt Git du projet correspondant de Google, libre sur GitHub : https://github.com/google/zopfli.

Puis, en se plaçant à la racine du dépôt, un petit :

make zopflipng

Vous compilera le tout.

La particularité de l'algorithme zopfli est de pouvoir être décompressé par les algorithmes deflate, gzip et zlib déjà largement implémentés et répandus (dans les navigateurs web, par défaut pour les logs dans GNU/Linux et donc également pour les fichiers PNG). Il est également amusant de noter que zopfli veut dire « petite tresse au beurre » en suisse allemand, et qu'il s'agit d'un clin d'œil au format de compression Brotli (également développé par Google et aux performances proches du LZMA), portant lui aussi le nom d'une viennoiserie suisse.

Pourquoi réinventer un algorithme de compression, et s'appliquer à le rendre compatible avec les outils de décompression existants ? Tout simplement parce quand on est Google, gagner 1% sur la taille d'un logo sans perte de qualité, ça représente tout de suite des économies astronomiques en terme de bande passante, et puis c'est toujours ça de pris sur le temps de chargement des pages. Or là, on parle de 5 à 15% de gain en pratique sur les PNG d'un site web.

2. Rentrons dans le vif du sujet

Maintenant qu'on a fixé le décor, voyons comment lancer ces commandes de manière efficace et optimisons, non plus la taille d'images, mais l'exécution de ces commandes. Pour rentrer dans le vif du sujet, on peut lancer ces re-compresseurs d'images à l'aide des commandes à tuyau suivantes, pour faire du traitement générique de fichiers par lot, parallélisé.

jpeqoptim :

find . -regextype posix-extended -iregex '.*(jpeg|jpg)' -print0 | xargs -0 -P $((`nproc` - 1)) jpegoptim -t

zopflipng :

find . -regextype posix-extended -iregex '.*png' -print0 | xargs -0 -P $((`nproc` - 1)) -I {} zopflipng -m --lossy_8bit --lossy_transparent -y {} {}

Ici, dans les deux cas la commande find se charge de trouver les fichiers et les signale à la commande xargs. On s'appuie, pour ce faire, sur une expression régulière insensible à la casse, histoire de ne laisser aucun fichier en réchapper. Même les noms de fichiers contenant des espaces sont supportés, grâce au couple d'arguments -print0 côté find et -0 côté xargs. Cette dernière va, elle, lancer les traitements, autant que le nombre de processeurs trouvés (moins un, histoire de pouvoir continuer à utiliser la machine ; avec l'hyperthreading d'Intel, un « divisé par deux » ne serait pas pire à ma connaissance) c'est le rôle de l'argument -P que l'on renseigne avec le traitement arithmétique shell $((`nproc` - 1)) sur le résultat de la commande nproc qui nous retourne le nombre de microprocesseurs du système. Enfin, dans le cas de la commande zopflipng, on est obligé de passer par un motif de remplacement du nom de fichier dans la commande, ici {} déclaré par l'argument -I, car la commande ne sait pas remplacer directement l'ancien fichier par le nouveau, ce qui est au contraire au comportement par défaut de jpegoptim (et peut surprendre…).

Du coup ça se lance, ça explore le disque depuis le dossier courant, occupe bien le CPU et libère de l'espace disque. Bien, mais ça prend plein de temps, or on peut accélérer les choses.

3. apt-build

Tout d'abord, on peut recompiler la commande qui compresse les images avec apt-build quand on est sous Debian. Pour ce faire, on commence par un petit :

apt install apt-build

Le process post-install de configuration demande pour quelle architecture compiler, or GCC connaît déjà votre processeur mieux que vous, répondre -march=natives'impose donc, puis ça nous demande quel niveau d'optimisation choisir pour la compilation, en indiquant que le niveau le plus avancé n'est pas fiable, restons donc au niveau intermédiaire…

On peut ensuite, lancer :

apt-build install jpegoptim

Attendre quelques minutes que ça compile, et si tout se passe bien, notamment parce que vous avez gardé les lignes qui commencent par deb-src dans votre fichier /etc/apt/source.lst et qui ne servent à ma connaissance qu'à ça, vous vous retrouvez avec un paquet .deb local, créé sur votre machine par apt-build et installé dans la foulée. Un petit tour dans Synaptic montre que la version du paquet en question est suffixée par un -aptbuild1, preuve qu’il s’agit bien du fruit de votre compilation.

Pour que tout se passe bien, je suis allé chercher un épinglage adéquat pour ce nouveau dépôt de paquets locaux (Siltaar étant mon pseudo) :

cat /etc/apt/preferences.d/50Siltaar

Package: *

Pin: release o=apt-build

Pin-Priority: 990

Package: *

Pin: release a=jessie-backports

Pin-Priority: 500

Package: *

Pin: release a=stable/updates

Pin-Priority: 500

Package: *

Pin: release a=stable

Pin-Priority: 500

On constate qu’ici tout tient en équilibre parce qu'il n'y a pas de dépôt unstable en jeu. Il faudrait donner à un tel dépôt une priorité inférieure au stable pour utiliser un paquet unstabletout seul sans contaminer le reste du système un peu plus à chaque mise à jour .

On peut alors s'attendre à des gains de performance de 5% à 15% par rapport à la version précompilée (qui ne tire pas spécifiquement parti des dernières fonctionnalités de votre microprocesseur). Pour tendre vers les 15% de gain, rien ne vous empêche de compiler aussi la commande xargs, la commande findet même la libc6 tant qu'on y est !

En regardant ce qui tourne sur ma Debian/Xfce4, j'ai constaté qu'il y a plusieurs icônes de ma barre de tâches qui cachent en fait un script Python lancé via python3. Python est recompilable également :

apt-build install python3 libpython3.4 libpython3.4-minimal libpython3.4-stdlib

aptitude markauto python3 libpython3.4 libpython3.4-minimal libpython3.4-stdlib

La deuxième ligne sert ici à remarquer comme « installé automatiquement » les paquets recompilés, qui sinon perdent ce statut de par l'attention particulière qu'on vient de leur porter.

Il faut compter une heure de compilation par paquet sur une machine à 3024 bogomips et 8Go RAM en 64bits...

Une fois lancés, on aurait bien recompilé qemu-kvm, firefox-esr ou encore aptitude, mais la compilation échoue dans ces cas-là sans autres interventions. Ce sont spontanément les programmes qui me viennent à l'esprit en matière de paquets recompilables et qui font attendre dans la vie de tous les jours. Leur recompilation méritera probablement un article à part entière...

4. prelink

Ce n'est pas tout, on peut encore faire gagner environ 10% de performance à notre jpegoptim, en pré-liant les bibliothèques dynamiques de fonction que la commande commence par chercher à son lancement. Il existe en effet une commande prelink, disponible dans le paquet Debian éponyme, dédiée à cet usage :

prelink jpegoptim find xargs

prelinkest une commande rapide très polie et pleine d'options. Elle permet notamment de revenir en arrière avec l'argument --undo, de vérifier qu'un programme a déjà été pré-lié (--verify) et de mettre en place des listes noires de bibliothèques à exclure du traitement (si on souhaite garder quelques bibliothèques en dynamiques).

Conclusion

Au travers de cet exemple pratique, ce sont des techniques éminemment génériques qui ont été présentées. Bien sûr, avant d'avoir regagné en économie de temps d'exécution, rien que le temps passé à compiler les paquets, il faut en avoir du JPEG à recompresser, mais ces astuces pour accélérer la vitesse d'exécution de programmes compilés sont réutilisables dans de nombreux cas de figure (encodage audio ou vidéo, compression ou conversion de fichiers en ligne de commandes...) et donc avec bien d'autres commandes. De plus, cet article abordait des sujets variés en autant d’invitations à explorer plus avant les problématiques abordées : pile d’exécution C et bibliothèques dynamiques, gestion des dépôts de paquets dans Debian et épinglage, nouveaux algorithmes de compression de données... J’espère que vous y aurez appris au moins quelques astuces. Si vous en avez appris beaucoup, voire pas assez, rappelez-vous qu’apprendre à se servir d’un GNU/Linux est un long chemin, et que même avec le temps, on ne maîtrise pas GNU/Linux, on devient humble.




Article rédigé par

Par le(s) même(s) auteur(s)

Solar Hammer : pourquoi les tâches solaires menacent les réseaux ?

Magazine
Marque
Hackable
Numéro
26
Mois de parution
septembre 2018
Spécialité(s)
Résumé

Ce phénomène des tâches solaires, découvert en 1859, est à l’origine de bourrasques de vent solaire qui, lors des périodes cycliques de forte activité, impactent sur Terre l’équilibre des phénomènes électriques et électromagnétiques sur lesquels s’appuie une grande partie de la civilisation occidentale.

Installer un portefeuille Bitcoin et effectuer un paiement

Magazine
Marque
Linux Pratique
Numéro
104
Mois de parution
novembre 2017
Spécialité(s)
Résumé
Effectuer un paiement en Bitcoin est une opération appelée à devenir courante vu le succès des monnaies numériques par chiffrement. Toutefois, ce n’est, sur le principe, pas tout à fait aussi simple qu’envoyer un courriel, et encore, en considérant ici leur version chiffrée… Nous allons donc consacrer ce tutoriel à regarder les différentes étapes de ce processus d’un peu plus près.

Les derniers articles Premiums

Les derniers articles Premium

Cryptographie : débuter par la pratique grâce à picoCTF

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

L’apprentissage de la cryptographie n’est pas toujours évident lorsqu’on souhaite le faire par la pratique. Lorsque l’on débute, il existe cependant des challenges accessibles qui permettent de découvrir ce monde passionnant sans avoir de connaissances mathématiques approfondies en la matière. C’est le cas de picoCTF, qui propose une série d’épreuves en cryptographie avec une difficulté progressive et à destination des débutants !

Game & Watch : utilisons judicieusement la mémoire

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Au terme de l'article précédent [1] concernant la transformation de la console Nintendo Game & Watch en plateforme de développement, nous nous sommes heurtés à un problème : les 128 Ko de flash intégrés au microcontrôleur STM32 sont une ressource précieuse, car en quantité réduite. Mais heureusement pour nous, le STM32H7B0 dispose d'une mémoire vive de taille conséquente (~ 1,2 Mo) et se trouve être connecté à une flash externe QSPI offrant autant d'espace. Pour pouvoir développer des codes plus étoffés, nous devons apprendre à utiliser ces deux ressources.

Raspberry Pi Pico : PIO, DMA et mémoire flash

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Le microcontrôleur RP2040 équipant la Pico est une petite merveille et malgré l'absence de connectivité wifi ou Bluetooth, l'étendue des fonctionnalités intégrées reste très impressionnante. Nous avons abordé le sujet du sous-système PIO dans un précédent article [1], mais celui-ci n'était qu'une découverte de la fonctionnalité. Il est temps à présent de pousser plus loin nos expérimentations en mêlant plusieurs ressources à notre disposition : PIO, DMA et accès à la flash QSPI.

Les listes de lecture

8 article(s) - ajoutée le 01/07/2020
Découvrez notre sélection d'articles pour faire vos premiers pas avec les conteneurs, apprendre à les configurer et les utiliser au quotidien.
11 article(s) - ajoutée le 02/07/2020
Si vous recherchez quels sont les outils du DevOps et comment les utiliser, cette liste est faite pour vous.
8 article(s) - ajoutée le 02/07/2020
Il est essentiel d'effectuer des sauvegardes régulières de son travail pour éviter de perdre toutes ses données bêtement. De nombreux outils sont disponibles pour nous assister dans cette tâche.
Voir les 49 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous