Archive for the ‘Programmation’ Category

Code Colorer avec PHP7

8 décembre 2016

J’ai récemment migré mon hébergement vers PHP 7. J’ai ensuite constaté que mes blogs sur lesquels étaient actif le plugin code colorer ne fonctionnaient plus. Malheureusement, ce plugin ne semble plus maintenu, et il ne faut donc pas compter sur une hypothétique mise à jour pour corriger le problème. Heureusement, certains proposent la solution. Je la reprend ici pour archives.

PHP Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in [...]/wp-content/plugins/codecolorer/codecolorer-core.php on line 50

Dans le fichier wp-content/plugins/codecolorer/codecolorer-core.php, trouvez les lignes suivantes (vers la ligne 50) :

/** Search content for code tags and replace it */
function BeforeHighlightCodeBlock($content) {
$content = preg_replace('#(\s*)\[cc([^\s\]_]*(?:_[^\s\]]*)?)([^\]]*)\](.*?)\[/cc\2\](\s*)#sie', '$this->PerformHighlightCodeBlock(\'\\4\', \'\\3\', $content, \'\\2\', \'\\1\', \'\\5\');', $content);
$content = preg_replace('
#(\s*)\<code(.*?)\>(.*?)\(\s*)#sie', '$this->PerformHighlightCodeBlock(\'\\3\', \'\\2\', $content, \'\', \'\\1\', \'\\4\');', $content);

return $content;
}

Et remplacer par :

/** Search content for code tags and replace it */
function BeforeHighlightCodeBlock($content) {
$content = preg_replace_callback('#(\s*)\[cc([^\s\]_]*(?:_[^\s\]]*)?)([^\]]*)\](.*?)\[/cc\2\](\s*)#si', function($matches){
return $this->PerformHighlightCodeBlock($matches[4], $matches[3], $matches[2], $matches[1], $matches[5]);
}, $content);
$content = preg_replace_callback('#(\s*)\<code(.*?)\>(.*?)\(\s*)#si', function($matches){
return $this->PerformHighlightCodeBlock($matches[3], $matches[2], '', $matches[1], $matches[4]);
}, $content);

return $content;
}

Linkage Qt sous Visual Studio : libgles_cm.lib

11 décembre 2011

J’ai acquis récemment une nouvelle machine pour le développement. Je fais notamment du développement sous Visual Studio 2008 avec Qt, grâce à l’add-in Qt pour Visual Studio. J’ai donc importé mes projets après avoir réinstallé l’ensemble de mes outils. A la première compilation, l’erreur suivante survient lors de l’étape de l’édition des liens :

LINK : fatal error LNK1181: impossible d'ouvrir le fichier en entrée 'libgles_cm.lib'

Après enquête, la solution est la suivante : sous Visual Studio : menu Projet –> Propriétés du projet –> Propriété de configuration (barre latérale à droite) –> Editeur de liens –> Entrée –> supprimer la bibliothèque problématique (libgles_cm.lib) dans la zone « Dépendances supplémentaires ».

Cette bibliothèque n’était pas présente dans mon projet initial, j’ignore donc pourquoi cette dépendance à été ajoutée de façon automatique et à mon insu… Il s’agit a priori d’une bibliothèque OpenGL. La seule différence entre les deux configuration des machines étant le passage de Qt 4.6.3 à 4.6.4.

Générer un dégradé en arc-en-ciel

3 novembre 2011

Pour un projet personnel (dont je reparlerais certainement plus tard sur ce blog), j’ai eu besoin de générer des points de couleur en fonction de la position de la valeur du point au sein d’un ensemble. Je souhaitais avoir quelque chose de continu, c’est à dire que 2 points ayant une valeur proche aient une couleur proche, et couvrir la plus large gamme possible de couleur, l’idéal étant d’avoir quelque chose qui se rapproche d’un arc en ciel.

Pour résumer, voici mes contraintes :

  • une variation continue des couleurs (autrement dit, hors de question de faire un saut du jaune au rouge par exemple si 2 points ont des valeurs voisines, chose que l’on obtient en général avec des algorithmes plus simplistes)
  • couvrir la plus large gamme possible de couleurs (pour résumer, je veux du rouge, du orange, du jaune, du vert, du bleu, du violet…)

C’est un problème d’apparence simple, mais qui nécessite d’être correctement modélisé pour parvenir à ses fins. Une simple étude du système RGB permet d’en trouver une solution. Traçons le graph des composantes rouges (R), vertes (V) et bleues (B) des couleurs ordonnées de l’arc en ciel. On obtient quelque chose comme ceci (on a en x les « numéro » des couleurs et en y la valeur entre 0 et 255 de chaque composante RGB. Les pastilles aux bases et aux sommets permettent de représenter la couleur résultante) :

RGB componant graphic

Graphique des composantes RVB

On voit ici que l’idée de l’algorithme est de ne faire varier qu’une seule composante à la fois.

Avec ce graphique, il est aisé de donner les fonctions résultantes des composantes R, V et B, qui sont de simple fonctions du premier degré, à définir par parties (l’objectif étant de d’avoir les valeurs de R, V et B sur l’intervalle [0;255], en ne faisant varier qu’une seule composante à la fois) :

  • Pour la composante rouge :
  (r) \left\{  \begin{array}{lrl}  \textrm{si } 0 \le x < 255 & :r= & 255 \\  \textrm{si } 255 \le x < 510 & :r= & 510-x \\  \textrm{si } 510 \le x < 1020 & :r= & 0 \\  \textrm{si } 1020 \le x \le 1275 & :r= & x-1020 \\  \textrm{si } 1275 \le x \le 1530 & :r= & 255 \\  \end{array}  \right.
  • Pour la composante verte :
  (v) \left\{  \begin{array}{lrl}  \textrm{si } 0 \le x < 255 & :v= & x \\  \textrm{si } 255 \le x < 765 & :v= & 255 \\  \textrm{si } 765 \le x < 1020 & :v= & 1020-x \\  \textrm{si } 1020 \le x \le 1530 & :v= & 0 \\  \end{array}  \right.
  • Pour la composante bleue :
  (b) \left\{  \begin{array}{lrl}  \textrm{si } 0 \le x < 510 & :b= & 0 \\  \textrm{si } 510 \le x < 765 & :b= & x-510 \\  \textrm{si } 765 \le x < 1275 & :b= & 255 \\  \textrm{si } 1275 \le x \le 1530 & :b= & 1530-x \\  \end{array}  \right.

Dans toutes ces formules, x représentant le « numéro » (ou l’indice) de la couleur que l’on souhaite obtenir. Si on a une valeur y comprise entre dans l’intervalle [y_{min};y_{max}], on peut obtenir x par la formule x = \dfrac{1530}{y_{max}-y_{min}} \times y.

A noter qu’ici, j’ai opté pour un intervalle de [0;1530] car il représente 6 times 255 soit le plus grand nombre de couleurs que l’on puisse obtenir avec cet algorithme (au delà, une même couleur pourrait avoir 2 numéros, ce qui serait bien sur inutile). Il est bien sur possible d’adapter cet algorithme de façon à avoir un nombre de nuances plus réduits (100 par exemple).

Cette algorithme produit ces variations (je vous présente ici la gamme complète des couleurs que peut générer l’algo) :

Dégradé généré par l'algorithme présenté

Dégradé généré par l’algorithme présenté

Passons au code, voici le code qui permet de générer les codes RGB correspondants aux valeurs. La fonction prend en argument l’intervalle et la valeur à partir de laquelle il faut  déterminer la couleur. Comme c’est du C++, la fonction retourne simplement un objet QColor (objet Qt).

QColor calcColor(double interval, double value){
QColor color;
int x = (1530/interval)*value;
int r;
int g;
int b;
if(x>=0 && x<255){
r = 255;
g = x;
b = 0;
}
if(x>=255 && x<510){
r = 510-x;
g = 255;
b = 0;
}
if(x>=510 && x<765){
r = 0;
g = 255;
b = x-510;
}
if(x>=765 && x<1020){
r = 0;
g = 1020-x;
b = 255;
}
if(x>=1020 && x<1275){
r = x-1020;
g = 0;
b = 255;
}
if(x>=1275 && x<=1530){
r = 255;
g = 0;
b = 1530-x;
}
color.setRgb(r, g, b);
return color;
}

A noter que cet algorithme devrait également fonctionner dans d’autres espaces de couleur que RGB (en CMY, cyan/magenta/jaune, notamment).

Utilisation de GeographicLib sous Visual Studio C++

21 octobre 2011

Je vous livre ici la solution à un problème qui m’a donné pas mal de fil à retordre : l’utilisation de la librairie GeographicLib (une bibliothèque de calcul de coordonnés géographique, notamment du « direct geodesic problem« , qui consiste à calculer une positon sur la Terre en connaissant une positon d’origine, une distance et un azimut(cap). Cette bibliothèque est également capable de faire des conversions entre les différents systèmes géodesiques existants). Je précise que la version utilisées ici est la 1.14

Mes problèmes furent multiples :

  1. Faire fonctionner la bibliothèque sous Visual Studio (2008 pour mon cas, mais les soucis auraient probablement étés les mêmes sous VS2005 ou VS2010)
  2. Comprendre comment elle fonctionne
  3. Réussir à compiler, en l’occurrence, j’avais des erreurs sur l »édition des liens (linker).

1) Installer et faire fonctionner la librairie sous VC2008

Pas de grosses difficultés ici, il faut juste ne pas se faire piéger par la doc qui présente (à ce jour) une erreur. Donc :

  • dans les paramètres du projet (Projet -> Propriété de…),
  • se rendre dans Propriété de configuration ->C/C++->Général->Autres répertoire include et renseigner : C:Program FilesGeographicLib-1.14include.
  • Dans Éditeur de liens->Général-> Répertoires de bibliothèques supplémentaires, renseigner C:Program FilesGeographicLib-1.14lib et non C:Program FilesGeographicLib-1.14include comme indiqué dans la documentation
  • Dans Éditeur de liens->Entrée->Dépendances supplémentaires, ajouter Geographic.lib
Je vais tâcher de les contacter pour leur indiquer cette erreur.

2) Comprendre comment elle fonctionne

Ici, j’ai eu des difficultés, car c’est l’une des premières fois que j’utilise une bibliothèque tierce (hors Qt, superbe doc,  et SDK matériels, qui ont souvent eut aussi une doc assez explicite avec des exemples), et assez peu utilisée. J’ai donc eu un mal terrible à trouver des exemples sur Internet. Lors de mes premiers essais, j’ai ainsi codé ainsi :

double lat1 = 46.908848;
double lon1 = 6.327472;
double azi1 = 59.16;
double s12 = 6216.28;
double lat2;
double lon2;
Geodesic::Direct(lat1, lon1, azi1, s12, &amp;lat2, &amp;lon2);

Ce qui générait à la compilation des erreurs du genre :

.main.cpp(295) : error C2665: 'GeographicLib::Geodesic::Direct' : aucune des 6 surcharges n'a pu convertir tous les types d'arguments
.GeographicLib/Geodesic.hpp(350): peut être 'GeographicLib::Math::real GeographicLib::Geodesic::Direct(GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real &amp;,GeographicLib::Geodesic::real &amp;) throw() const'

Je vous livre donc la syntaxe correcte qui est :

double lat1 = 46.908848;
double lon1 = 6.327472;
double azi1 = 59.16;
double s12 = 6216.28;
double lat2;
double lon2;
const Geodesic&amp; g = Geodesic::WGS84;
g.Direct(lat1, lon1, azi1, s12, lat2, lon2);

3) Parvenir à compiler/linker

A la compilation, enfin, à l’édition des liens pour être précis, j’obtenais les erreurs suivantes :

1>Édition des liens en cours...
1>Geographic.lib(Geodesic.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_MSC_VER=1600' non valide rencontrée ; ignorée
1>Geographic.lib(Geodesic.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0' non valide rencontrée ; ignorée
1>Geographic.lib(GeodesicLine.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_MSC_VER=1600' non valide rencontrée ; ignorée
1>Geographic.lib(GeodesicLine.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0' non valide rencontrée ; ignorée
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: char const * __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::c_str(void)const " (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::erase(unsigned int,unsigned int)" (?erase@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@II@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: static unsigned int __cdecl std::char_traits<char>::length(char const *)" (?length@?$char_traits@D@std@@SAIPBD@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>Geographic.lib(Geodesic.obj) : error LNK2019: symbole externe non résolu "__declspec(dllimport) void __cdecl std::_Xlength_error(char const *)" (__imp_?_Xlength_error@std@@YAXPBD@Z) référencé dans la fonction "public: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Xlen(void)const " (?_Xlen@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEXXZ)
1>Geographic.lib(Geodesic.obj) : error LNK2019: symbole externe non résolu "__declspec(dllimport) void __cdecl std::_Xout_of_range(char const *)" (__imp_?_Xout_of_range@std@@YAXPBD@Z) référencé dans la fonction "public: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Xran(void)const " (?_Xran@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEXXZ)

Après pas mal de lecture sur le net et avoir bidouillé a peu près tous les paramètres de l’éditeur de liens de Visual Studio, je me suis résolu à recompiler moi même la librairie. Pour cela, il faut télécharger le zip du code source de GeographicLib (ici par exemple). Les développeurs ont même eu l’idée de fournir des fichiers projets pour VS2005 (GeographicLib-vc8.sln), 2008 (GeographicLib-vc9.sln) et 2010 (GeographicLib-vc10.sln) (répertoire windows de l’archive). J’ouvre donc le fichier qui correspond à ma version de Visual Studio et j’ai compilé la bibliothèque en mode Release. Il en ressort un beau fichier .lib d’environ 1800 ko (contre 1300 ko pour celui fourni). Après remplacement du fichier Geographic.lib fourni par ce nouveau fichier, la compilation et l’édition des liens se déroule à merveille, et la bibliothèque semble fonctionner.

Dans mon immense bonté, je vous fourni cette librairie compilée avec Visual Studio C++ 2008 (je ne sais pas si elle fonctionne avec VC2005 ou VC2010) : Geographic.lib.