En 2020, Gabriel Lavallée, un de mes étudiants au Collège Lionel-Groulx, m'a posé des questions sur la compression RLE, et j'ai fait un petit exemple pour l'aider à comprendre les enjeux. Cet exemple compresse des pixels RGB dans un tableau dynamique d'entiers non-signés contenant en pratique des paires {combien,quoi}, représentant chaque pixel par un entier pour les besoins de cette transformation. Si ça vous intéresse, le voici.
Le programme n'utilisera que des outils de la bibliothèque .NET de base. |
|
J'ai créé un petit type Pixel représentant un triplet RGB. Les fonctions clés pour nos besoins sont :
J'ai ajouté une méthode de conversion en string pour faciliter l'affichage des instances de Pixel |
|
La compression RLE en soi s'exprime assez aisément :
Il restera toujours une partie résiduelle à la fin de la boucle, car par définition, la dernière séquence de valeurs identiques consécutives ne sera pas terminée par un élément de valeur différente (sinon, ce ne serait pas la dernière!). Pour cette raison, les éléments des indices dans l'intervalle [i,pix.Count) sont ajoutés au résultat pour terminer le travail Cet algorithme pourrait se généraliser en l'exprimant de manière générique, mais c'est moins agréable en C# que ce ne le serait en C++ (imposition d'interfaces, ralentissement du code) |
|
Un programme de test naïf montre que le tout fonctionne. Notez que Main affiche les valeur de rle en format décimal, mais un affichage hexadécimal serait plus clair. |
|
Que doit-on faire si l'on souhaite compresser des données avec transformations? Par exemple, si on ne souhaite tenir compte que des teintes de rouge de nos instances de Pixel?
Une solution simple est de paramétrer l'algorithme de compression en lui ajoutant une transformation à appliquer aux éléments. Le code suit; notez que je n'ai pas répété ce qui demeure identique, par souci de simplicité et d'économie.
En acceptant une transformation en paramètre, la fonction de compression peut comparer les versions transformées de chaque Pixel, et compresser la séquence à traiter sur la base de ces valeurs transformées. |
|
La version « ordinaire » (sans transformation) de la fonction de compression devient une délégation vers la fonction générale, mais dans laquelle la transformation est une fonction identité (p => p) |
|
Le programme de test dans ce cas montre une compression « ordinaire » et une autre qui ne tient compte que du ton de rouge de chaque Pixel |
|
Voilà!