CImg est une petite bibliothèque générique C++ open-source développée initialement pour le traitement d'images 2D ou 3D [1], très légère, multi-plateforme et facile à prendre en main. Elle est développée dans l'équipe IMAGE du laboratoire CNRS GREYC à Caen [2]. Elle a la particularité de tenir dans un seul fichier 'CImg.h' [3]. Ce dernier point, décrié par certains, est pourtant essentiel, et permet une simplicité d'utilisation très appréciable et qui ne se dément pas au fil des sorties successives.
La version 1.1.5 sort aujourd'hui, et apporte comme toujours son lot de nouveautés et corrections de bugs. Quelques points notables sont cependant à souligner :
- Le changement de licence pour le code source de la bibliothèque, qui utilise maintenant la nouvelle variante CeCiLL-C, proche de la LGPL. Le reste des fichiers (exemples, documentation) reste en CeCiLL classique (compatible GPL). Ainsi la bibliothèque CImg en elle-même peut être utilisé de manière moins restrictive.
- GREYCstoration [3], petit utilitaire de restauration d'images en ligne de commande basé sur CImg passe du coup en version 2.4, avec quelques optimisations supplémentaires. Il reste par contre en version CeCiLL et donc complètement "libre".
- CImg peut maintenant gérer les modes plein-écran sous Unix, grâce à l'extension Xrandr qui peut être utilisée de manière optionnelle. C'était précédemment possible seulement sous Windows.
CImg peut ainsi servir à créer de petits jeux ou animations en plein écran, les performances générales d'affichages ayant été également améliorées. - Un système de plug-ins permet très facilement d'ajouter des fonctions supplémentaires à l'intérieur même de la bibliothèque, sans avoir à modifier le code source. Quelques plug-ins ont déjà été proposés par des contributeurs extérieurs, et j'espère que cet aspect va encore se développer
Pour finir, il est important de souligner que CImg essaye de rester minimal, dans le sens ou il est toujours possible de le compiler sans bibliothèques autres que celles du C++ standard.
C'est une bibliothèque en fait très modulable malgré sa structure en un seul fichier, et l'utilisation de bibliothèques extérieures permet simplement de lui activer des fonctionnalités spécifiques (pour l'affichage notamment).
Bref, une petite bibliothèque a essayer pour tous ceux qui s'intéressent au traitement et à l'affichage d'images en C++.
[1] Bibliothèque CImg : http://cimg.sourceforge.net
[2] Equipe GREYC/Image : http://www.greyc.ensicaen.fr/EquipeImage/
[3] Le code source de CImg.h : http://cimg.cvs.sourceforge.net/cimg/CImg/CImg.h?view=markup
[4] GREYCstoration : http://www.greyc.ensicaen.fr/~dtschump/greycstoration/
# les copies d'écran
Posté par BAud (site web personnel) . Évalué à 4.
http://cimg.sourceforge.net/screenshots.shtml
les exemples sont toujours sympathiques (ils ont été mis à jour ?)
et la démo en live http://www.greyc.ensicaen.fr/~dtschump/greycstoration/demons(...) (ne pas en abuser, ça fatigue le serveur :/ )
# Apu updates ?
Posté par _Hitek_ (site web personnel) . Évalué à 3.
http://www.haypocalc.com/wiki/Gimp_Plugin_GREYCstoration
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 3.
[^] # Re: Apu updates ?
Posté par Victor STINNER (site web personnel) . Évalué à 3.
Un mec m'a envoyé une version 0.3 du plugin qui utilise la version précédente de CImg et l'algorithme GREYCstoration. Je pense qu'il faudrait créer un projet sur Savanah, Gna, BerliOS ou autre pour que d'autres puisse participer au développement du plugin.
Moi j'attend toujours que CImg soit découpé en modules pour qu'il soit un minimum lisible. Je me refuse à travailler sur un fichier monolythique qui mélange appel à la biblitohèque libpng, appel à Windows, gestion des entrées X11, algorithme de traitement d'image, etc.
Contactez-moi si vous voulez voir une nouvelle version du plugin Gimp.
Haypo
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 1.
Est-ce que quand tu linkes ton code avec une autre bibliothèque, tu regarde son code avant pour être sûr que ca te plait ? Si le code ne te plait pas mais que tu as besoin de sa fonctionnalité, tu la recodes depuis le début ?
De la même manière, le code source du logiciel GREYCstoration utilise la bibliothèque CImg. Le fait que cette bibliothèque est en fait un header et non pas un binaire pré-compilé ne change rien au problème (si vraiment ca te gêne, tu peux facilement générer un fichier de code objet avec toutes les fonctions de CImg pour tous les types dont tu as besoin).
Ne serait-ce pas un peu une sorte de snobisme de programmation ?
[^] # Re: Apu updates ?
Posté par Victor STINNER (site web personnel) . Évalué à 2.
Elle ne me satisfait pas, elle est trop lente :-) Je voulais l'optimiser (ex: en utilisant de l'assembleur SIMD, MMX, SSE, Altivec & co).
De plus, l'essentiel du code de GREYCstoration est dans CImg (tous les traitements sur l'image).
Ne serait-ce pas un peu une sorte de snobisme de programmation ?
Oui, il me semble.
Je suis pas contre que quelqu'un reprenne le peu de code que j'ai écrit. De tout façon il est sous GPL, je ne peux même pas m'y opposer :-)
Haypo
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 5.
Ce n'est pas en découpant CImg en plusieurs fichiers qu'elle va aller plus vite.
Si tu as des optimisations de fonctions à proposer, dis le moi, je pourrai s toujours les intégrer dans CImg.
Je suppose que ce sera uniquement sur des fonctions précises, ca devrait pas être trop dur de faire un flag qui permet de choisir à la compilation les versions ASM ou C++ des fonctions, de la même façon que des flags permettent de compiler des fonctions pour X11 ou pour la lib GDI32 de windows.
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
Cela permet au nouveau entrant de savoir tout de suite ou aller chercher les fonctions à modifier. Cela évite de connaitre tout le code avant de commencer une modif.
J'imagine que bouger un .h est plus simple qu'une arboressence, mais cela revient en fait au même.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 3.
Le fait que ces classes soient définies dans plusieurs fichiers ou dans un seul ne change absolument rien ni à la vitesse de compilation, ni à la structure intrinsèque de la bibliothèque.
De toute facon, il n'y a que 5 classes, qui sont toutes nécéssaires en général.
Un découpage en fichiers headers multiples est artificiel et ne changera pas plus la structure de la bibliothèque que si je découpais CImg par blocs de 10 lignes ou je ne sais quelle autre décomposition.
Pour le nouveau entrant qui s'interesserait à la bibliothèque en elle-même, je pense même que c'est plus facile de faire un 'Search' du nom de la fonction dans un seul fichier plutot qu'un grep pour savoir deja dans quel fichier se trouve la fonction, puis un search.
Un bon compilo sait de plus aujourd'hui compiler uniquement les fonctions dont il a besoin, c'est d'autant vrai pour les bibliothèques templates qui ont un fonctionnement particulier.
Conclusion : Découpage ou pas, le compilo mettra non seulement le même temps à compiler, mais en plus produira le même code.
Après, ton a-priori sur la clarté du code de CImg... Passe 5 minutes à vraiment analyser le code et les classes, et dis moi si tout cela te semble vraiment incompréhensible. J'ai vu trop de gens affolé juste par le nombre de lignes qui disait : "non c'est trop gros, ca doit être le bordel". Bin en fait, non. Tout ca est extrêmement structuré.
Et d'après le nombre de contributions sans cesse croissant que je recois, je suppose que ca doit pas être si compliqué à comprendre pour des gens extérieurs.
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 4.
Pour la vitesse de compilation, si ton code est découpé, sous unix, le include <cimg_windows.h> ne sera pas executé, et les lignes correspondante non parsé, c'est peut-être negligable, j'en sais trop rien. Mais je trouve que le temps de compile des exemples est long.
Pour le nouveau entrant qui s'interesserait à la bibliothèque en elle-même, je pense même que c'est plus facile de faire un 'Search' du nom de la fonction dans un seul fichier plutot qu'un grep pour savoir deja dans quel fichier se trouve la fonction, puis un search.
Si ton code est correctement structuré, tu sais tout de suite quel fichier ouvrir pas besoin de grep.
Eviter l'effet masse, c'est aussi un moyen d'avoir plus de codeurs.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 2.
Tout ce qui est affichage (et qui est refait pour chaque plateforme) est la classe CImgDisplay, et c'est tout.
La encore, la séparation est faite, simplement dans une classe à part. Si tu veux mettre cette classe à part dans un autre fichier, pourquoi pas, mais ca sera plus pour la forme (enfin pour ta forme :) ), puisque la séparation est déjà faite.
Tout le code propre au traitement d'image est de la même façon dans la classe CImg, qui elle ne contient aucun code spécifique à une plateforme donnée.
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
J'ai bricolé avec hier soir. Le plus chiant c'est vraiment les temps de compilations. Plusieurs minutes sur un pc pas trop vieux pour un seul fichier ! (gcc 4.0.1) C'est d'autant plus énervant sur un bi-cpu avec le 2ième cpu idle (car il n'y a qu'un fichier à compiler).
Sinon, cela a l'air simple d'emplois.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 4.
Ca fait maintenant 7 ans que je travaille sur CImg, et crois moi j'ai eu l'occasion de me poser des questions sur la structure de la bibliothèque pendant tout ce temps. Pour chaque choix que j'ai fait, j'ai pesé le pour et le contre, et je peux le justifier. Et si la bibliothèque a ajourd'hui cette forme, il y a des (bonnes à mon sens) raisons que je peux justifier.
Alors bien sûr, en programmation, on ne peut pas plaire à tout le monde, mais l'intérêt du libre c'est que tu peux reprendre le code et le modifier à ta sauce si ca te tente.
Beaucoup de gens ont critiqué CImg, simplement parce que son style ne rentrait pas dans les standards de programmation qu'ils avaient appris à l'école, et cela sans avoir lu plus de 3 lignes de son code. Je trouve ca ridicule : il faut savoir sortir des sentiers battus de temps en temps, sinon on coderait encore tout en basic.
Ne crois pas qu'on puisse pondre quasiment 20000 lignes de code (la longueur totale de CImg, ce qui est très peu en réalité) sans jamais se remettre en question.
Boost a un style propre et des buts qui n'ont rien a voir avec CImg, ca n'a aucun sens de les comparer.
[^] # Re: Apu updates ?
Posté par Victor STINNER (site web personnel) . Évalué à 2.
Sinon, plutôt que d'utiliser des flags de compilation pour choisir les options de CImg à activer, il serait intéressant de découper la bibliothèque en module. Un programme pour X11 qui voudra permettre l'enregistrement en JPEG utilisera :
En tout cas, je pense qu'au niveau de la compilation, c'est kif-kif. Le précompilateur, cc je crois bien, fait bien son boulot.
C'est vraiment pour rendre le code de CImg (mais pas des programmes qui l'utilisent) plus lisible (plus facile à relire, à maintenir, à faire évoluer, etc.).
Haypo
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 1.
Personnellement, j'ai loin d'avoir le temps (et l'envie) de faire ce découpage que je juge un peu "artificiel".
En ce qui me concerne, je trouve le code de CImg très lisible, car compact et bien structuré.
Mettre ca en trois ou quatre fichiers m'importe peu, d'autant que les IDE de programmation actuels te permettent de naviguer aisément à travers les classes et les namespaces en dehors de toute structuration par fichiers.
[^] # Re: Apu updates ?
Posté par dinomasque . Évalué à 3.
Mauvais éditeur de texte : changer d'éditeur de texte.
Certains éditeurs de texte ou IDE ont de sympathiques menus déroulants permettant d'atteindre la définition d'une fonction/classe rapidement (BeIDE faisait ça très bien par exemple).
La plupart des bons éditeurs de texte permettent également de replier le code et d'avoir plusieurs vues sur un même fichier.
Dès lors je ne vois pas quel confort de multiples fichiers pourraient apporter.
BeOS le faisait il y a 20 ans !
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 1.
Il faut savoir sortir des sentiers battus de temps en temps, sinon on coderait encore tout en basic.
Cela n'a pas de rapport en l'occurence... Je ne considère pas le fait de tout mettre dans un seul fichier comme ayant un seul avantage sur celui d'avoir quelques fichiers. L'utilisation d'opérateur ternaire est une vrai avancé.
Avec un IDE qui retrouve les tags, cela peut se faire mais bon...
Sinon avec des header précompilé, je gagne plus de 60% du temps de compilation cela devient accèptable.
J'ai essayé l'option de compilation -ftree-vectorize, cela change très peu les temps d'execution, je suis un peu déçu.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 1.
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 2.
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 4.
La fonction offset() est très utilisé forcément. En la modifiant par :
return (x+width*y)+(width*height*z+width*height*depth*v);
Le but est de réduire le nombre de dépendance read-after-write qui tue le parralèlisme.
J'obtient 10% de perf en plus sur le test sur processeur athlon. Par contre, cela ne change rien sur une machine pentium.
Les 3 tests qui sont dans CImg_demo qui rendent des fps sont en fait très dépendant de la vitesse d'affichage donc non représentatif pour les calculs.
J'ai essayé de modifier offset() pour que v sois la 1er dimension et non la dernière. Telle que c'est codé ici, on a 3 plans de couleur, un vert, un rouge, un bleu. Avec v en première dimension, on a R,V,B,R,V,B,R,V,B,... Cela dépend beaucoup des calculs mais je pense qu'en général, quand on utilise une couleur d'un pixel on a beaucoup de chance d'immédiatement utiliser les autres couleurs. Dans le "rangement" RVB, les 3 couleurs sont dans la même ligne de cache, donc en théorie, les acces devrait être plus rapide.
A prioris d'autre macro utilise le layout mémoire sous -entendu donc il faudrait modifier plus de chose que offset() pour faire le test.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 3.
J'ai opté pour un alignement 'plan par plan' plutot que de manière 'entrelacée'. Ce choix effectivement pénalise l'accès pixel par pixel quand on fait des traitement couleurs.
Mais inversement, c'est très adapté pour toute opération qui se fait composant par composante, comme le filtrage (flou, erosion, gradient, convolution, et j'en oublie d'autres), en fait toute opération intrinsèquement scalaire qui nécéssite l'accès aux voisins directs.
Je pense que si tu changes CImg pour avoir une structure entrelacée R,G,B,R,G,B, tu vas gagner sur certaines opérations mais tu vas en perdre sur d'autres. Le gain final (si il y en a un) n'est pas si évident à estimer.
Bien sûr j'ai pensé à faire des CImg qui pourrait avoir plusieurs manières différentes de stocker les données, manière qui seraient donnée à la construction par exemple. On rendrait ainsi la classe plus générique. Mais franchement, je trouve que c'est un peu du détail d'informaticien, et ca alourdirait pas mal le code pour un gain que l'utilisateur final qui veut juste faire du traitement d'image ne verrait pas forcément.
CImg ne s'adresse évidemment pas à des gens voulant faire de l'animation temps réel à la base, même si c'est possible sur des machines puissantes. Il est clair que des bibliothèques plus adaptées existent (SDL et consort).
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
C'est pour ça que je parlais de gain théorique. Je ne crois pas qu'il existe des astuces en c++ qui permète d'induire un choix de layout mémoire selon l'utilisation qu'il en est fait. Si cela existait l'utilisateur n'aurait pas à s'en soucier.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Tu as pu vérifier l'augmentation de performance avec la modification de offset () ?
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 2.
Pour ta version de offset, j'ai pas testé, je vais voir ca, ca a l'air intéressant.
Est-ce que ca risque pas d'être moins performant sur d'autres archi (proc PPC ou Sun par exemple ?)
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
En gros, une ligne de cache fait 32 ou 64 octets selon le modèle de processeur. Donc, je pense que cela serait super interrescant d'avoir les voisins dans cette ligne de cache. Par exemple, si tu découpes ton images en cube de 4*4*4, tu as tous les voisins 4*4 dans la même ligne de cache ou presque. C'est du tailing, cela permet d'augmenter la localité d'acces aux donnés.
"La première sécurité est la liberté"
[^] # Re: Apu updates ?
Posté par David Tschumperlé (site web personnel) . Évalué à 2.
Je pensais en écrivant offset qu'il fallait que je minimise le nombre de multiplications faites mais j'imagine que c'est des vieux reflexes de programmeurs de 68000 qui n'ont plus lieu d'être avec les proc maintenant.
Je commit.
[^] # Re: Apu updates ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
"La première sécurité est la liberté"
# oups un seul fichier...
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Sinon qu'en est-il des performances ? Si je recodes moi-mêmes, j'aurais 10x plus de perf ou bien le code utilise les astuces du genre de celle de blas ? (pour faire des traitements léger mais temps réel)
"La première sécurité est la liberté"
[^] # du c++ ?!
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
// Create two display window, one for the image, the other for the color profile.
CImgDisplay
main_disp(image,"Color image (Try to move mouse pointer over)",0),
draw_disp(500,400,"Color profile of the X-axis",0);
cimg_mapXYZV(dest,x,y,z,k) {
const double X = ((double)x/img1.dimx()-0.5)*ca + ((double)y/img1.dimy()-0.5)*sa;
if (X+0.5<pmin) alpha=0; else {
if (X+0.5>pmax) alpha=1; else alpha=(X+0.5-pmin)/(pmax-pmin);
}
dest(x,y,z,k) = (unsigned char)((1-alpha)*img1(x,y,z,k) + alpha*img2(x,y,z,k));
}
Le code précédent qui ressemble à une fonction est en fait dans le corps de main. Certe il y a peu de ligne de code, mais j'avoue avoir du mal à le comprendre ce code. A quoi sert de faire du c++, si c'est aussi facile à lire que du perl.
"La première sécurité est la liberté"
[^] # Re: oups un seul fichier...
Posté par David Tschumperlé (site web personnel) . Évalué à 2.
Il faut bien voir que CImg est programmé en essayant d'être multi-plateforme et multi-compilateurs. Ca peut paraitre un détail mais rendre un code qui compile avec plusieurs compilateurs, c'est déjà pas facile. La redéfinition de PI a été nécéssaire ici pour une de ces raisons (un compilateur particulier (je ne sais plus lequel) ne connaissait pas le PI de math.h...).
Pleins d'autres trucs qui peuvent paraitre superflus sont présent justement pour que ca compile sur bcp de compilos.
C'est dommage, mais c'est le prix à payer pour avoir quelque chose de "portable".
[^] # Re: oups un seul fichier...
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
"La première sécurité est la liberté"
[^] # Re: oups un seul fichier...
Posté par dwd . Évalué à 1.
Tu voulais peut être dire "violent" ? ;-)
# dépendance xlib
Posté par Sytoka Modon (site web personnel) . Évalué à 1.
GREYCstoration a une dépendance avec la xlib pour faire un affichage en cours de calcul. Cet affichage étant facultatif (option à mettre en ligne de commande), la dépendance est toujours forte ou faites selon le nouveau système de plugin ?
En gros, peux t'on maintenant l'utiliser sur une machine ou il n'y a pas la xlib ?
[^] # Re: dépendance xlib
Posté par David Tschumperlé (site web personnel) . Évalué à 1.
# Merci merci
Posté par nazcafan . Évalué à 5.
Merci aussi pour le passage en Cecill-C, ça va me servir pour mon travail.
Une seule remarque pour rejoindre Haypo, c'est vrai que je trouve le code imbittable, ceci dit, si on n'a pas à regarder dedans on s'en moque, mais comment fait-il pour s'y retrouver lui-même ?
# OMFG !
Posté par Xavier Maillard . Évalué à 2.
Encore une fois, chapeau ! Je suis sûr que tu peux postuler au concours du code le plus ... hum ... gruik n'est pas le mot mais presque. C'est touffu comme j'aime ;)
Allez, ne te décourage pas c'est vraiment du bon boulot (en plus la TNI, c'est mon dada, j'adore ça ;)).
[^] # Re: OMFG !
Posté par Victor STINNER (site web personnel) . Évalué à 2.
http://www.ioccc.org/
Ça m'intéresserait de connaître le même genre de site mais pour Python ! Perl, c'est de la triche, il intègre un obscursificateur de base :-p
http://en.wikipedia.org/wiki/Just_another_Perl_hacker
Haypo
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.