Olivier Mengué – Code & rando - Tag - code
2024-03-25T15:25:14+01:00
urn:md5:57e646ab8ca85028168daaaa985aa995
Dotclear
Une icône pour les liens vers Wikipédia
urn:md5:fb78d349b98fe7bdad22307dee0bd503
2007-11-03T19:31:26+00:00
2008-09-06T17:03:47+00:00
Olivier Mengué
Code
bloggingcodeCSSfaviconhowtoHTMLicônewebdevWikipédia
<p>J'ai juste ajouté une petite touche à la feuille de style de ce blog (dont <a href="http://o.mengue.free.fr/blog/2007/08/25/39-syntax-highlighting-on-this-blog-using-semantic-tags-and-vim" hreflang="en">j'ai déjà longuement parlé</a> en anglais) : une petite icône pour signaler les liens vers <a href="http://fr.wikipedia.org/" hreflang="fr">Wikipédia</a>.</p>
<p>J'ai récupéré l'icône du site en ligne de commande avec <a href="http://www.gnu.org/software/wget/" hreflang="en">Wget</a> :</p>
<pre class="terminal unix">
<samp class="prompt shell">$ </samp><kbd>wget -O wikipedia.ico http://fr.wikipedia.org/favicon.ico</kbd>
<samp class="wget">--19:23:35-- http://fr.wikipedia.org/favicon.ico
=> `wikipedia.ico'
Résolution de fr.wikipedia.org... 145.97.39.155
Connexion vers fr.wikipedia.org|145.97.39.155|:80... connecté.
requête HTTP transmise, en attente de la réponse... 200 OK
Longueur: 318 [image/x-icon]
100%[====================================>] 318 --.--K/s
19:23:35 (30.79 MB/s) - « wikipedia.ico » sauvegardé [318/318]</samp>
</pre>
<p>Je l'ai ensuite convertie à la taille 14x14 au format <a href="http://fr.wikipedia.org/wiki/Graphics_Interchange_Format">GIF</a> avec l'outil <a href="http://www.imagemagick.com/www/convert.html" hreflang="en"><code>convert</code></a> d'<a href="http://www.imagemagick.com/" hreflang="en">ImageMagick</a> :</p>
<pre class="terminal unix">
<samp class="prompt shell">$ </samp><kbd>convert wikipedia.ico -resize 14x14 wikipedia.gif</kbd>
</pre>
<p>L'image résultante faisait 595 octets. L'utilisation de l'application en ligne <a href="http://tools.dynamicdrive.com/imageoptimizer/" hreflang="en">Image Optimizer</a> m'a permis de réduire le nombre de couleurs de l'image à 16 et de réduire la taille à 167 octets.</p>
<p>En suivant <a href="http://www.meganmcdermott.com/2006/10/26/marking-external-links-with-css/" hreflang="en">Megan McDermott</a>, j'ai modifié ma feuille de style pour ajouter la ligne suivante :</p>
<pre class="code vim vimft-css no-link-icon">
<span class="Statement">a</span><span class="Special">[</span>href^<span class="Special">=</span><span class="Constant">"<a href="http://fr.wikipedia.org/" hreflang="fr" class="no-icon">http://fr.wikipedia.org/</a>"</span><span class="Special">]</span><span class="Normal">,</span> <span class="Statement">a</span><span class="Special">[</span>href^<span class="Special">=</span><span class="Constant">"<a href="http://en.wikipedia.org/" class="no-icon" hreflang="en">http://en.wikipedia.org/</a>"</span><span class="Special">]</span> <span class="Identifier">{</span> <span class="Type">background</span>:<span class="Identifier">url(</span><span class="Constant">wikipedia.gif</span><span class="Identifier">)</span> <span class="Constant">100%</span> <span class="Type">no-repeat</span>; <span class="Type">padding-right</span>: <span class="Constant">16px</span> <span class="Identifier">}</span>
</pre>
<p>Il peut être utile parfois de désactiver ce style localement ou pour les blocs de code :</p>
<pre class="code vim vimft-css">
<span class="Statement">pre</span><span class="Identifier">.code</span> <span class="Statement">a</span>:<span class="PreProc">link</span>, <span class="Statement">pre</span><span class="Identifier">.terminal</span> <span class="Statement">a</span>:<span class="PreProc">link</span>,
<span class="Identifier">.no-link-icon</span> <span class="Statement">a</span>:<span class="PreProc">link</span>,
<span class="Statement">a</span>:<span class="PreProc">link</span><span class="Identifier">.no-icon</span>
<span class="Identifier">{</span> <span class="Type">background</span>: <span class="Type">inherit</span>; <span class="Type">padding-right</span>: <span class="Type">inherit</span> <span class="Identifier">}</span>
</pre>
<p><strong>Mise à jour 2007-11-05 à 22:25 :</strong> mes règles pour les exceptions ne fonctionnent pas ! Je me suis fait avoir par les <a href="http://www.w3.org/TR/REC-CSS2/cascade.html#specificity" hreflang="en">règles de précédence des règles CSS</a> ! Il va falloir que je corrige cela...</p>
<p><strong>Mise à jour 2007-11-05 à 22:46 :</strong> voici, j'espère, la correction. Il faut que j'augmente le poids des règles d'exception en augmentant <em>le nombre d'attributs ou de pseudo-classes dans le sélecteur.</em></p>
<pre class="code vim vimft-css">
<span class="Statement">pre</span><span class="Identifier">.code</span> <span class="Statement">a</span>:<span class="PreProc">link</span><span class="Special">[</span>href<span class="Special">]</span>, <span class="Statement">pre</span><span class="Identifier">.terminal</span> <span class="Statement">a</span>:<span class="PreProc">link</span><span class="Special">[</span>href<span class="Special">]</span>,
<span class="Identifier">.no-link-icon</span> <span class="Statement">a</span>:<span class="PreProc">link</span><span class="Special">[</span>href<span class="Special">]</span>,
<span class="Statement">a</span>:<span class="PreProc">link</span><span class="Identifier">.no-icon</span><span class="Special">[</span>href<span class="Special">]</span>
<span class="Identifier">{</span> <span class="Type">background</span>: <span class="Type">inherit</span>; <span class="Type">padding-right</span>: <span class="Type">inherit</span> <span class="Identifier">}</span>
</pre>
http://o.mengue.free.fr/blog/post/2007/11/03/45-une-icone-pour-les-liens-vers-wikipedia#comment-form
http://o.mengue.free.fr/blog/feed/atom/comments/45
Rotation JPEG sans perte, suite
urn:md5:fc0886cd485887fad37a624308d5fc7f
2007-11-03T17:16:24+00:00
2008-04-06T23:32:47+00:00
Olivier Mengué
Code
codeEXIFexiftoolGnomeImage::ExifToolJPEGjpegtranlibjpeg-progsmetadataNautilusPerlrotationUbuntu
<p>Suite à <a href="http://o.mengue.free.fr/blog/2007/10/21/43-rotation-jpeg-vraiment-sans-perte">mon précédent post</a>, j'ai profité qu'<a href="http://search.cpan.org/~exiftool/Image-ExifTool-7.00/exiftool">exiftool</a> est un module Perl pour re-développer en <b>Perl</b> mon outil de rotation des images JPEG <i>vraiment</i> sans perte. Voici ci-dessous le code et les astuces pour l'intégration dans <a href="http://fr.wikipedia.org/wiki/Nautilus_%28logiciel%29">Nautilus</a>.</p> <p>Le principe reste le même : utiliser <code>jpegtran</code> faire la rotation de l'image principale en préservant toutes les données EXIF, extraire les imagettes et leur appliquer la même rotation avant de les réintégrer dans le fichier iimage.</p>
<p>Cet outil peut être intégré à Nautilus dans le menu contextuel « Scripts ». il suffit pour cela de créer quelques liens symboliques :</p>
<pre class="terminal unix">
<samp class="prompt shell">$ </samp><kbd class="shell">ln -s jpgrot ~/.gnome2/nautilus-scripts/"Rotation JPEG 90°"</kbd>
<samp class="prompt shell">$ </samp><kbd class="shell">ln -s jpgrot ~/.gnome2/nautilus-scripts/"Rotation JPEG 180°"</kbd>
<samp class="prompt shell">$ </samp><kbd class="shell">ln -s jpgrot ~/.gnome2/nautilus-scripts/"Rotation JPEG 270°"</kbd>
</pre>
<p>Voici le code :</p>
<pre class="code vim vimft-perl">
<span class="PreProc">#!/usr/bin/perl</span>
<span class="Statement">use strict</span>;
<span class="Statement">use warnings</span>;
<span class="Statement">require</span> <span class="Constant">v5.8.0</span>;
<span class="Statement">use </span><a href="http://search.cpan.org/~exiftool/Image-ExifTool-7.00/lib/Image/ExifTool.pod">Image::ExifTool</a>;
<span class="Statement">use </span><a href="http://search.cpan.org/~nwclark/perl-5.8.8/lib/IPC/Open2.pm">IPC::Open2</a>;
<span class="Statement">my</span> <span class="Identifier">$title</span> = <span class="Constant">'</span><span class="Constant">Rotation JPEG sans perte</span><span class="Constant">'</span>;
<span class="Statement">my</span> <span class="Identifier">$angle</span>;
<span class="Statement">if</span> (<span class="Identifier">$0</span> =~<span class="Statement"> /</span><span class="Special">(</span><span class="Constant">90|180|270</span><span class="Special">)</span><span class="Statement">/</span>) {
<span class="Identifier">$angle</span> = <span class="Identifier">$1</span>;
} <span class="Statement">elsif</span> (<span class="Identifier">$ARGV[</span><span class="Constant">0</span><span class="Identifier">]</span> <span class="Statement">eq</span> <span class="Constant">'</span><span class="Constant">-a</span><span class="Constant">'</span> && <span class="Identifier">$#ARGV</span> > <span class="Constant">1</span>) {
<span class="Statement">shift</span> <span class="Identifier">@ARGV</span>;
<span class="Identifier">$angle</span> = (<span class="Constant">360</span> + <span class="Statement">shift</span> <span class="Identifier">@ARGV</span>) % <span class="Constant">360</span>;
} <span class="Statement">else</span> {
<span class="Comment">#$angle = `zenity --title "$title" --scale --text "Angle de rotation :" --value=90 --min-value=90 --max-value=270 --step=90`;</span>
<span class="Identifier">$angle</span> = <span class="Statement">`</span><span class="Constant">zenity --title "</span><span class="Identifier">$title</span><span class="Constant">" --list --text "Angle de rotation :" --column "Degrés" 90 180 270</span><span class="Statement">`</span>;
<span class="Identifier">$?</span> <span class="Operator">and</span> <span class="Statement">exit</span> <span class="Constant">1</span>;
}
<span class="Comment">#system('zenity', '--info', '--title', $title, '--text', "Angle : $angle");</span>
<span class="Comment">#$angle || exit 1;</span>
<span class="Statement">my</span> <span class="Identifier">@files</span>;
<span class="Statement">if</span> (<span class="Identifier">$ENV</span><span class="Identifier">{</span><span class="Constant">NAUTILUS_SCRIPT_SELECTED_FILE_PATHS</span><span class="Identifier">}</span>) {
<span class="Identifier">@files</span> = <span class="Statement">split</span><span class="Statement"> /</span><span class="Special">\n</span><span class="Statement">/</span>, <span class="Identifier">$ENV</span><span class="Identifier">{</span><span class="Constant">NAUTILUS_SCRIPT_SELECTED_FILE_PATHS</span><span class="Identifier">}</span>;
} <span class="Statement">else</span> {
<span class="Identifier">@files</span> = <span class="Identifier">@ARGV</span>;
}
<span class="Identifier">@files</span> = <span class="Statement">grep</span> <span class="Statement">/</span><span class="Special">\.</span><span class="Constant">jpe</span><span class="Special">?</span><span class="Constant">g$</span><span class="Statement">/i</span>, <span class="Identifier">@files</span>;
<span class="Comment">#system 'zenity', '--list', '--column', 'Fichier', @files;</span>
<span class="Statement">my</span> <span class="Identifier">$exifTool</span> = <span class="Statement">new</span> Image::ExifTool;
<span class="Statement">my</span> <span class="Identifier">$exifTool2</span> = <span class="Statement">new</span> Image::ExifTool;
<span class="Statement">for</span> <span class="Statement">my</span> <span class="Identifier">$file</span> (<span class="Identifier">@files</span>) {
<span class="Statement">next</span> <span class="Statement">unless</span> <span class="Statement">-f</span> <span class="Identifier">$file</span> && <span class="Statement">-r</span> <span class="Identifier">$file</span>;
<span class="Statement">my</span> <span class="Identifier">$pid</span> = <span class="Statement">open</span>(<span class="Statement">my</span> <span class="Identifier">$rotated</span>, <span class="Constant">'</span><span class="Constant">-|</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">jpegtran</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">-rotate</span><span class="Constant">'</span>, <span class="Identifier">$angle</span>, <span class="Constant">'</span><span class="Constant">-optimize</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">-perfect</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">-copy</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">all</span><span class="Constant">'</span>, <span class="Identifier">$file</span>);
<span class="Statement">binmode</span>(<span class="Identifier">$rotated</span>);
<span class="Statement">my</span> <span class="Identifier">$img</span> = <span class="Statement">do</span> { <span class="Statement">local</span> (<span class="Identifier">$/</span>); <<span class="Identifier">$rotated</span>> };
<span class="Statement">close</span> <span class="Identifier">$rotated</span>;
<span class="Statement">waitpid</span> <span class="Identifier">$pid</span>, <span class="Constant">0</span>;
<span class="Comment"># $fields = ['ImageWidth', 'ImageHeight', 'ThumbnailImage', 'PreviewImage'];</span>
<span class="Statement">my</span> <span class="Identifier">$info</span> = <span class="Identifier">$exifTool</span><span class="Identifier">->ImageInfo</span>(<span class="Identifier">\$img</span>);
<span class="Comment">#print map {$_.$/} sort keys %$info;</span>
<span class="Statement">my</span> <span class="Identifier">$portrait</span> = <span class="Identifier">$$info</span><span class="Identifier">{</span><span class="Constant">ImageHeight</span><span class="Identifier">}</span> > <span class="Identifier">$$info</span><span class="Identifier">{</span><span class="Constant">ImageWidth</span><span class="Identifier">}</span>;
<span class="Comment">#system 'zenity', '--info', '--text', "$file($$info{ImageWidth}x$$info{ImageHeight}): ".($portrait ? 'portrait' : 'paysage');</span>
<span class="Statement">for</span> <span class="Statement">my</span> <span class="Identifier">$subimg</span> ((<span class="Constant">'</span><span class="Constant">ThumbnailImage</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">PreviewImage</span><span class="Constant">'</span>)) {
<span class="Statement">next</span> <span class="Statement">unless</span> <span class="Statement">exists</span> <span class="Identifier">$$info{$subimg}</span>;
<span class="Statement">my</span> <span class="Identifier">$ref_img</span> = <span class="Identifier">$$info{$subimg}</span>;
<span class="Statement">my</span> <span class="Identifier">$info</span> = <span class="Identifier">$exifTool2</span><span class="Identifier">->ImageInfo</span>(<span class="Identifier">$ref_img</span>, [<span class="Constant">'</span><span class="Constant">ImageWidth</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">ImageHeight</span><span class="Constant">'</span>]);
<span class="Statement">if</span> (<span class="Identifier">$angle</span> == <span class="Constant">180</span> || (<span class="Identifier">$$info</span><span class="Identifier">{</span><span class="Constant">ImageHeight</span><span class="Identifier">}</span> > <span class="Identifier">$$info</span><span class="Identifier">{</span><span class="Constant">ImageWidth</span><span class="Identifier">}</span>) != <span class="Identifier">$portrait</span>) {
<span class="Comment">#print "Rotation $subimg\n";</span>
<span class="Statement">my</span> (<span class="Identifier">$jpegtran_in</span>, <span class="Identifier">$jpegtran_out</span>);
<span class="Statement">my</span> <span class="Identifier">$pid</span> = open2(<span class="Identifier">$jpegtran_out</span>, <span class="Identifier">$jpegtran_in</span>,
<span class="Constant">'</span><span class="Constant">jpegtran</span><span class="Constant">'</span>,
<span class="Constant">'</span><span class="Constant">-rotate</span><span class="Constant">'</span>, <span class="Identifier">$angle</span>,
<span class="Constant">'</span><span class="Constant">-optimize</span><span class="Constant">'</span>,
<span class="Constant">'</span><span class="Constant">-perfect</span><span class="Constant">'</span>,
<span class="Constant">'</span><span class="Constant">-copy</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">all</span><span class="Constant">'</span>
);
<span class="Statement">binmode</span> <span class="Identifier">$jpegtran_in</span>;
<span class="Statement">binmode</span> <span class="Identifier">$jpegtran_out</span>;
<span class="Statement">syswrite</span> <span class="Identifier">$jpegtran_in</span>, <span class="Identifier">$$ref_img</span>;
<span class="Statement">close</span> <span class="Identifier">$jpegtran_in</span>;
<span class="Statement">my</span> <span class="Identifier">$img</span> = <span class="Statement">do</span> { <span class="Statement">local</span> (<span class="Identifier">$/</span>); <<span class="Identifier">$jpegtran_out</span>> };
<span class="Statement">close</span> <span class="Identifier">$jpegtran_out</span>;
<span class="Statement">waitpid</span> <span class="Identifier">$pid</span>, <span class="Constant">0</span>;
<span class="Comment"># jpegtran adds a JFIF group. We drop it.</span>
<span class="Comment"># Ne marche pas pour l'instant</span>
<span class="Identifier">$exifTool2</span><span class="Identifier">->ExtractInfo</span>(<span class="Identifier">\$img</span>);
<span class="Identifier">$exifTool2</span><span class="Identifier">->SetNewValue</span>(<span class="Constant">'</span><span class="Constant">JFIF</span><span class="Constant">'</span>); <span class="Comment"># Delete JFIF group</span>
<span class="Identifier">$exifTool2</span><span class="Identifier">->WriteInfo</span>(<span class="Identifier">\$img</span>);
<span class="Identifier">$exifTool</span><span class="Identifier">->SetNewValue</span>(<span class="Identifier">$subimg</span>, <span class="Identifier">\$img</span>);
}
}
<span class="Identifier">$exifTool</span><span class="Identifier">->SetNewValue</span>(<span class="Constant">'</span><span class="Constant">FileModifyDate</span><span class="Constant">'</span>, <span class="Identifier">$$info</span><span class="Identifier">{</span><span class="Constant">CreateDate</span><span class="Identifier">}</span>);
<span class="Comment">#$file = substr($file, 0, -4)."-$angle.jpg";</span>
<span class="Statement">unlink</span> <span class="Identifier">$file</span>;
<span class="Identifier">$exifTool</span><span class="Identifier">->WriteInfo</span>(<span class="Identifier">\$img</span>, <span class="Identifier">$file</span>) || <span class="Statement">warn</span> <span class="Constant">"</span><span class="Identifier">$!</span><span class="Constant">"</span>;
<span class="Identifier">$exifTool</span><span class="Identifier">->SetFileModifyDate</span>(<span class="Identifier">$file</span>);
}
</pre>
<p>Il me reste à tranformer cela sous la forme d'une vraie extension Nautilus, grâce à <a href="http://www.grumz.net/index.php?q=taxonomy/term/2/9">Nautilus Actions</a>. Mais je cherche pour cela à utiliser les icônes de <a href="http://www.gimp.org/">Gimp</a> du menu Image → Transformer. Je ne suis pas arrivé à trouver où elles sont stockées sur <a href="http://www.ubuntu-fr.org/">Ubuntu</a> 7.10.</p>
Rotation JPEG vraiment sans perte
urn:md5:241ab2e2e2ae0d53ed99090c994cd8d5
2007-10-21T23:38:51+00:00
2008-04-07T00:02:40+00:00
Olivier Mengué
Code
bashcodeEXIFexiftoolImage::ExifToolJPEGjpegtranlibjpeg-progsmetadatarotationUbuntu
<p>Avez-vous déjà examiné en détail les méta-données EXIF d'une photo numérique après une rotation soit-disant « sans perte » ? Si vous l'avez fait avec un outil tel que <code><a href="http://search.cpan.org/~exiftool/Image-ExifTool-6.90/exiftool">exiftool</a></code>, vous avez sûrement du constaté la catastrophe. Certains outils de rotation perdent toutes les données EXIF, d'autres une partie des paramètres de prise de vue ou le champ Software... Et aucun ne fait la rotation des imagettes de prévisualisation, ni ne préserve la date de création originelle du fichier. J'ai essayé sous <a href="http://www.ubuntu.com/">Ubuntu 7.10</a>, <code>F-Spot</code>, <code>jpegtran</code> (paquet <code>libjpeg-progs</code>) et <code>exiftran</code>. Chacun a ses défauts.</p>
<p>Je vous propose donc ici la solution personnalisée que j'ai développée ce week-end en utilisant <code>jpegtran</code> et <code>exiftool</code>. Ce n'est pas forcément une solution universelle, mais elle est satisfaisante pour les photos issues de mon APN (sous réserve que mon outil d'observation </p> <p>Une image JPEG issue de mon appareil photo numérique (Nikon Coolpix E995) contient les données suivantes :</p>
<ul>
<li>les données graphique de l'image principale (2048x1536 en compression FINE) ;</li>
<li>les métadonnées EXIF ;</li>
<li>l'image de prévisualisation (PreviewImage) au format 320x240, pour l'affichage sur l'écran de l'APN : c'est un fichier JPEG complet embarqué ;</li>
<li>l'image de prévisualisation (ThumbnailImage) au format 160x120, pour l'affichage dans les logiviles de classement, dans Nautilus ou l'Explorateur Windows.</li>
</ul>
<p><code>jpegtran</code> sait faire la rotation de l'image principale sans perte (c'est à dire, pas de décompression/compression) en préservant les données EXIF, mais il copie les imagettes telles quelles, sans les tourner. <code>exiftran</code> tourne bien l'image principale et la <code>ThumbnailImage</code> mais il corrompt (d'après exiftool) les MarkerNotes et la PreviewImage.</p>
<p><code>exiftool</code>, un outil très complet de modification des données EXIF, dispose d'une fonctionnalité permettant d'extraire les imagettes, et plus tard de les remplacer. Cette fonction est également utile pour vérifier que la rotation de l'imagette a bien été effectuée.</p>
<p>Exemple :</p>
<pre class="terminal unix">
<samp class="prompt shell">$ </samp><kbd>exiftool -b -ThumbnailImage <var>DSCN4821.JPG</var> | exiftool -</kbd>
<samp>ExifTool Version Number : 6.90
File Type : JPEG
MIME Type : image/jpeg
Image Width : 160
Image Height : 120
Image Size : 160x120</samp>
<samp class="prompt shell">$ </samp><kbd>exiftool -b -PreviewImage <var>DSCN4821.JPG</var> | exiftool -</kbd>
<samp>ExifTool Version Number : 6.90
File Type : JPEG
MIME Type : image/jpeg
Image Width : 320
Image Height : 240
Image Size : 320x240</samp></pre>
<p>J'ai donc combiné <code>jpegtran</code> et <code>exiftool</code> en appliquant <code>jpegtran</code> à l'image principale puis aux imagettes. Le fichier est converti en place (l'original est écrasé) et la date de création du fichier est définie comme la date de prise de vue extraite des informations EXIF. J'en ai aussi profité pour appliquer l'option <code>-optimize</code> de <code>jpegtran</code> pour gagner au passage quelques kilo-octets.</p>
<p>Voici le code :</p>
<pre class="code vim vim-sh vim-bash">
<span class="Comment">#!/bin/bash</span>
<span class="Comment"># <a href="http://o.mengue.free.fr/">http://o.mengue.free.fr/</a></span>
<span class="Identifier">function</span> _jpegrot
<span class="Special">{</span>
<span class="Statement">typeset</span> <span class="Identifier">angle</span><span class="Operator">="</span><span class="PreProc">$1</span><span class="Operator">"</span>
<span class="Statement">typeset</span> <span class="Identifier">f</span><span class="Operator">="</span><span class="PreProc">$2</span><span class="Operator">"</span>
<span class="Special">[[</span> <span class="Operator">"</span><span class="Constant">x</span><span class="PreProc">$2</span><span class="Operator">"</span> <span class="Statement">=</span> *.<span class="Operator">[</span>jJ<span class="Operator">][</span>pP<span class="Operator">]</span>*<span class="Operator">[</span>gG<span class="Operator">]</span> <span class="Special">]]</span> <span class="Operator">||</span> <span class="Statement">return</span> <span class="Constant">0</span>
<span class="Statement">typeset</span> <span class="Identifier">b</span><span class="Operator">=</span><span class="PreProc">$(</span><span class="Statement">expr</span><span class="Special"> </span><span class="Operator">"</span><span class="Constant">x</span><span class="PreProc">$f</span><span class="Operator">"</span><span class="Special"> : </span><span class="Operator">'</span><span class="Constant">x</span><span class="Special">\(</span><span class="Constant">.*</span><span class="Special">\)</span><span class="Constant">\....$</span><span class="Operator">'</span><span class="PreProc">)</span>
<span class="Statement">typeset</span> <span class="Identifier">new</span><span class="Operator">="</span><span class="PreProc">$b</span><span class="Constant">.tmp.JPG</span><span class="Operator">"</span>
<span class="Statement">typeset</span> <span class="Identifier">prv</span><span class="Operator">="</span><span class="PreProc">$b</span><span class="Constant">.prv.JPG</span><span class="Operator">"</span>
<span class="Statement">typeset</span> <span class="Identifier">thb</span><span class="Operator">="</span><span class="PreProc">$b</span><span class="Constant">.thb.JPG</span><span class="Operator">"</span>
exiftool -b -PreviewImage -w <span class="Operator">"</span><span class="Constant">.prv.JPG</span><span class="Operator">"</span> -execute -b -ThumbnailImage -w <span class="Operator">"</span><span class="Constant">.thb.JPG</span><span class="Operator">"</span> -common_args <span class="Operator">"</span><span class="PreProc">$f</span><span class="Operator">"</span>
jpegtran -rotate <span class="Operator">"</span><span class="PreProc">$angle</span><span class="Operator">"</span> -optimize -perfect -copy all <span class="Operator">"</span><span class="PreProc">$f</span><span class="Operator">"</span> <span class="Operator">></span> <span class="Operator">"</span><span class="PreProc">$new</span><span class="Operator">"</span>
<span class="Statement">mv</span> -f -- <span class="Operator">"</span><span class="PreProc">$new</span><span class="Operator">"</span> <span class="Operator">"</span><span class="PreProc">$f</span><span class="Operator">"</span>
jpegtran -rotate <span class="Operator">"</span><span class="PreProc">$angle</span><span class="Operator">"</span> -optimize -perfect -copy all <span class="Operator">"</span><span class="PreProc">$prv</span><span class="Operator">"</span> <span class="Operator">|</span> exiftool -overwrite_original <span class="Operator">"</span><span class="PreProc">$f</span><span class="Operator">"</span> <span class="Operator">'</span><span class="Constant">-PreviewImage<=-</span><span class="Operator">'</span> <span class="Operator">></span> /dev/null
jpegtran -rotate <span class="Operator">"</span><span class="PreProc">$angle</span><span class="Operator">"</span> -optimize -perfect -copy all <span class="Operator">"</span><span class="PreProc">$thb</span><span class="Operator">"</span> <span class="Operator">|</span> exiftool -overwrite_original <span class="Operator">"</span><span class="PreProc">$f</span><span class="Operator">"</span> <span class="Operator">'</span><span class="Constant">-ThumbnailImage<=-</span><span class="Operator">'</span> <span class="Operator">'</span><span class="Constant">-DateTimeOriginal>FileModifyDate</span><span class="Operator">'</span> <span class="Operator">></span> /dev/null
<span class="Statement">rm</span> -f -- <span class="Operator">"</span><span class="PreProc">$prv</span><span class="Operator">"</span> <span class="Operator">"</span><span class="PreProc">$thb</span><span class="Operator">"</span>
<span class="Special">}</span>
<span class="Statement">typeset</span> <span class="Identifier">angle</span><span class="Operator">="</span><span class="PreProc">$1</span><span class="Operator">"</span>
<span class="Statement">shift</span>
<span class="Statement">for</span> f <span class="Statement">in</span> <span class="Operator">"</span><span class="PreProc">$@</span><span class="Operator">"</span>
<span class="Statement">do</span>
_jpegrot <span class="Operator">"</span><span class="PreProc">$angle</span><span class="Operator">"</span> <span class="Operator">"</span><span class="PreProc">$f</span><span class="Operator">"</span>
<span class="Statement">done</span>
</pre>
<p>Exemple d'utilisation :</p>
<pre class="terminal unix">
<samp class="prompt shell">$ </samp><kbd>jpegrot <var>90</var> <var>DSCN4821.JPG</var></kbd>
</pre>
Le clavier français sous le DOS de Vista
urn:md5:360bd775d86e61a2eba60025cf709bb1
2007-09-02T19:09:55+00:00
2008-10-21T00:37:51+00:00
Olivier Mengué
Général
autoexec.ntclaviercmd.execodecommand.comDOSKB16VistaWindows
<p class="update"><strong>Mise à jour 2008-08-30 :</strong> Cette astuce a été sélectionnée par le magazine <em><a href="http://www.ordinateur-individuel.com/">L'Ordinateur Individuel</a></em> et publiée dans le numéro 208 (septembre 2008) page 136 comme <em>astuce du mois</em>.</p>
<p>Nostalgie, nostalgie... le DOS c'est toute ma jeunesse. Le manuel du MS-DOS 5.0 est d'ailleurs le premier livre d'informatique que j'ai lu. Même sous Windows, j'ai toujours systématiquement une fenêtre d'« invite de commandes » toujours ouverte. Et la première chose que je fais sur un nouveau PC Windows, c'est d'assigner le raccourci <kbd class="key">Ctrl+Alt+C</kbd> à l'invite de commandes MS-DOS. La deuxième, c'est <kbd class="key">Ctrl+Alt+N</kbd> pour le Bloc-Notes (N comme NotePad). Et la troisième, c'est d'installer mon fichier <code>.INF</code> qui ajoute une entrée <em>Ouvrir un shell</em> dans le menu contextuel de l'Explorateur Windows.</p>
<p>Alors de temps en temps je vais voir comment évoluent les articles de Wikipédia dédiés au <a href="http://en.wikipedia.org/wiki/MS-DOS">MS-DOS</a> pour vérifier qu'ils ne racontent pas trop de bêtises, les corriger à l'occasion, et éventuellement encore apprendre quelque chose. C'est donc dans la section <a href="http://en.wikipedia.org/wiki/MS-DOS#Windows_NT">Windows NT</a> que j'ai vu quelques commandes que j'ai vu quelques commandes que j'ai voulu vérifier par l'expérience sur Windows Vista.</p>
<pre class="terminal cmd">
<samp>Microsoft Windows [version 6.0.6000]
Copyright (c) 2006 Microsoft Corporation. Tous droits réservés.
</samp><samp class="prompt cmd">C:\Users\<var>Dolmen</var>></samp><kbd>ver</kbd>
<samp>
Microsoft Windows [version 6.0.6000]
</samp><samp class="prompt cmd">C:\Users\<var>Dolmen</var>></samp><kbd>command /k ver</kbd>
<samp>
MS-DOS Version 5.00.500
</samp><samp class="prompt cmd">C:\USERS\<var>DOLMEN</var>></samp>
</pre>
<p>Rien de spécial jusque là.</p>
<pre class="terminal cmd">
<samp class="prompt cmd">C:\USERS\<var>DOLMEN</var>></samp><kbd>cd </kbd>
</pre>
<p>Mais là, <strong>oh stupeur !</strong> Pas moyen de taper un '\'. La combinaison de touches <kbd class="key">AltGr+8</kbd> ne fonctionne pas ! En fait, <strong>le clavier est en QWERTY</strong> dans <code>COMMAND.COM</code> !</p>
<p>En investiguant un peu plus, j'ai pu vérifier que ce sont tous les programmes pur MS-DOS qui ne tiennent plus compte de la configuration du clavier français mais utilisent au lieu de cela une configuration américaine du clavier. Par exemple <code>debug.exe</code> ou <code>edit.com</code>. Vous pouvez tester avec tous les <code>.COM</code> (ceux-là, contrairement aux <code>.EXE</code>, vous êtes sûrs que ce sont des programmes DOS) :</p>
<pre class="terminal cmd">
<samp class="prompt cmd">C:\Users\<var>Dolmen</var>></samp><kbd>dir %windir%\System32\*.com</kbd>
<samp> Le volume dans le lecteur C s'appelle <var>XXX</var>
Le numéro de série du volume est <var>YYYY-ZZZZ</var>
Répertoire de <var>C:\Windows</var>\System32
02/11/2006 10:31 11 776 chcp.com
02/11/2006 09:09 50 648 COMMAND.COM
02/11/2006 10:32 13 824 diskcomp.com
02/11/2006 10:32 11 264 diskcopy.com
18/09/2006 23:43 69 886 edit.com
02/11/2006 10:32 35 328 format.com
02/11/2006 10:35 56 320 graftabl.com
02/11/2006 09:09 19 694 GRAPHICS.COM
02/11/2006 09:09 14 710 <em>KB16.COM</em>
02/11/2006 09:09 1 131 LOADFIX.COM
02/11/2006 10:32 25 088 mode.com
02/11/2006 10:32 20 992 more.com
02/11/2006 10:32 16 384 tree.com
02/11/2006 10:35 6 656 win.com
14 fichier(s) 353 701 octets
0 Rép(s) <var>VV VVV VVV VVV</var> octets libres
</samp></pre>
<p>Vous aurez peut-être noté la présence de <code>KB16.COM</code> qui semble une piste à explorer :</p>
<pre class="terminal cmd">
<samp class="prompt cmd">C:\USERS\<var>DOLMEN</var>></samp><kbd class="cmd">kb16 /?</kbd>
<samp>Configures a keyboard for a specific language.
KEYB [xx[,[yyy][,[drive:][path]filename]]] [/E] [/ID:nnn]
xx Specifies a two-letter keyboard code.
yyy Specifies the code page for the character set.
[drive:][path]filename Specifies the keyboard definition file.
/E Specifies that an enhanced keyboard is installed.
/ID:nnn Specifies the keyboard in use.
</samp><samp class="prompt cmd">C:\USERS\<var>DOLMEN</var>></samp><kbd class="cmd">chcp</kbd>
<samp>Page de codes active : 850
</samp><samp class="prompt cmd">C:\USERS\<var>DOLMEN</var>></samp><kbd>kb16 fr,850 /E</kbd>
<samp>
</samp><samp class="prompt cmd">C:\USERS\<var>DOLMEN</var>></samp>
</pre>
<p>Voilà, c'est réparé... pour cette session ! Mais au prix de la perte de 6 Ko de mémoire conventionnelle (comparer avant et après avec <code>mem /C</code>). Et vous aurez noté que <code>KB16.COM</code> n'est pas traduit : Microsoft ne semble plus attacher autant d'importance à la traduction de ses produits.</p>
<p class="update"><strong>Mise à jour 2008-10-20 :</strong> La solution ci-dessous est obsolète. J'ai trouvé la vraie solution au problème, bien plus simple. <a href="http://o.mengue.free.fr/blog/post/2007/09/02/41-le-clavier-francais-sous-le-dos-de-vista#c3972">Sautez au commentaire 26</a>.</p>
<p>Pour charger automatiquement <code>KB16.COM</code> dans les prochaines sessions, il faut ajouter l'appel dans <code>%windir%\System32\autoexec.nt</code>. Mais comme avec Vista, rien n'est simple en raison de la protection paranoïaque des commandes d'administration, voici la marche à suivre :</p>
<ol>
<li>Dans le menu <em>Démarrer</em>, <em>Tous les programmes</em>, <em>Accessoires</em>, cliquez avec le bouton droit sur <em>Invite de commandes</em> puis <em>Exécuter en tant qu'administrateur</em>.</li>
<li>Chargez le clavier français et lancez <code>edit.com</code> :
<pre class="terminal cmd">
<samp>Microsoft Windows [version 6.0.6000]
Copyright (c) 2006 Microsoft Corporation. Tous droits réservés.
</samp><samp class="prompt cmd">C:\Windows\system32></samp><kbd class="cmd">KB16 fr,850 /E</kbd>
<samp>
</samp><samp class="prompt cmd">C:\WINDOWS\SYSTEM32></samp><kbd class="cmd">edit autoexec.nt</kbd>
</pre>
Pourquoi <code>edit.com</code> ? On aurait pu aussi utiliser le Bloc-Notes (<code>notepad.exe</code>). Sauf que l'on souhaite ici entrer des accents qui seront affichés dans la page de code du terminal, c'est à dire <a href="http://fr.wikipedia.org/wiki/Page_de_code_850">850</a>. Or le Bloc-Notes ne connaît que les encodages ANSI (cp1252), Unicode (ucs-2le), Unicode Big Endian (ucs2-be) et UTF-8.</li>
<li>Tapez <kbd class="key">Ctrl+Fin</kbd> et collez les lignes suivantes (pas avec <em>Copy</em> du menu <em>Edit</em> d'<code>edit.com</code>, mais avec <em>Modifier</em>, <em>Coller</em> dans le menu système de la fenêtre) :
<pre class="code vim vimft-dosbatch">
lh <span class="Identifier">%SystemRoot%</span>\system32\KB16 fr,850 <span class="Special">/E</span>
<span class="Statement">if</span><span class="Operator"> not errorlevel</span> <span class="Constant">1</span> <span class="Identifier">echo</span><span class="Constant"> Clavier français activé.</span>
</pre></li>
<li>Quittez en enregistrant : <kbd class="key">Alt+F</kbd>, <kbd class="key">x</kbd>, <kbd class="key">Entrée</kbd>.</li>
</ol>
http://o.mengue.free.fr/blog/post/2007/09/02/41-le-clavier-francais-sous-le-dos-de-vista#comment-form
http://o.mengue.free.fr/blog/feed/atom/comments/41
TiddlyWiki and favicon
urn:md5:afc660a2b2915dc4f92732e3a83ee51d
2007-08-28T21:00:41+00:00
2007-09-16T12:39:20+00:00
Olivier Mengué
Code
browsercodefaviconFirefoxHTMLMSIETiddlyWikiwebdevWindows
<p><a href="http://www.tiddlywiki.com/" hreflang="en">TiddlyWiki</a> is a standalone wiki that is fully interactive and fully contained in a single HTML file. Here is a tip to add a <a href="http://en.wikipedia.org/wiki/Favicon" hreflang="en">favicon</a> to your wiki.</p>
<p>To enable saving you have to give to the browser some special permissions allowing the JavaScript code to write to your disk. When using it with Microsoft Internet Explorer, the easy way to enable saving is to just rename your wiki as <code>.hta</code> to transform it into an "<a href="http://msdn2.microsoft.com/en-us/library/ms536471.aspx" hreflang="en">HTML Application</a>", as Microsoft calls it.</p>
<p>But you can do better with HTML Applications than just decreasing the security level. I was particularly interested in a better integration with Windows. I wanted in particular to change the icon of the window that appears in the taskbar (I commonly have about 30-40 windows opened on my desktop). This is quite easy: you just have to add an <code><HTA:APPLICATION ICON="myfile.ico"></code> tag the <code><head></code> section of the HTML file.</p>
<p>Here is how to do it the TiddlyWiki way:</p>
<ol>
<li>Get an icon and save it as <code>tiddlywiki.ico</code> in the same directory as your <code><var>wiki</var>.hta</code> file. For example: <a href="http://www.tiddlywiki.org/favicon.ico">http://www.tiddlywiki.org/favicon.ico</a>. You can also create you own icon <a href="http://tools.dynamicdrive.com/favicon/" hreflang="en">here</a> or <a href="http://www.htmlkit.com/services/favicon/" hreflang="en">here</a>.</li>
<li>Edit the built-in tiddler <strong>MarkupPreHead</strong></li>
<li>Insert the following text just after <code><!--{{{--></code>:
<pre class="code vim vimft-html">
<span class="Comment"><!</span><span class="Comment">--[if IE]></span>
<span class="Comment"><HTA:APPLICATION ID="oHTA" APPLICATIONNAME="<var title="The title of your wiki">My wiki</var>" ICON='<var title="Your icon file: a local file or an URL">tiddlywiki.ico</var>'/></span>
<span class="Comment"><![endif]--</span><span class="Comment">></span>
<span class="Identifier"><</span><span class="Statement">link</span><span class="Identifier"> </span><span class="Type">rel</span><span class="Identifier">=</span><span class="Constant">'shortcut icon'</span><span class="Identifier"> </span><span class="Type">href</span><span class="Identifier">=</span><span class="Constant">'<var title="Your icon file: a local file or an URL">tiddlywiki.ico</var>'</span> <span class="Type">type</span><span class="Identifier">=</span><span class="Constant">'image/vnd.microsoft.icon '</span><span class="Identifier">/></span>
</pre>
</li>
<li>Reload your <code><var>wiki</var>.hta</code>. That's it!</li>
</ol>
<p>I now have to explore how to convert this to a <a href="http://www.tiddlywiki.com/#Plugins">plugin</a>...</p>
http://o.mengue.free.fr/blog/post/2007/08/28/40-tiddlywiki-et-les-favicon#comment-form
http://o.mengue.free.fr/blog/feed/atom/comments/40
Stations Vélib’ : v2.0
urn:md5:2e4ce0720926ff2f6a656953fbe250f0
2007-08-12T23:15:52+00:00
2009-02-08T22:28:43+00:00
Olivier Mengué
Code
cartecodehackMaemoMaemo MappermapNokia N800ParisPOIVélib'XSLT
<p>Voici une nouvelle version de mon script de conversion des stations Vélib’ en base POI pour Maemo Mapper sur Nokia N800 (voir <a href="http://o.mengue.free.fr/blog/2007/08/02/32-une-carte-des-stations-velib-sur-nokia-n800">mon post précédent</a>).</p>
<p>Parmi les améliorations :</p>
<ul>
<li>un script pour automatiser le processus de transformation </li>
<li>le renseignement du champ <code>poi_id</code>, ce qui corrige le problème d'édition des POI </li>
<li>un index sur la table <code>POI</code> sur les champs latitude, longitude en espérant que cela améliore les temps d'accès. En pratique, je n'ai constaté aucune amélioration ;</li>
<li>4 catégories de POI au lieu d'une seule, pour créer votre propre base des stations : Station Vélib’, Station Vélib’ corrigée, Station Vélib’ validée, Station Vélib’ erronée ;</li>
<li>des modifications d'implémentaiton XSLT : l'utilisation de <a href="http://www.w3.org/TR/xslt#for-each"><code>xsl:foreach</code></a> et un traitement exhaustif des caractères de l'adresse de la station.</li>
</ul>
<p>Lisez la suite pour le nouveau code...</p> <p><strong>Relisez d'abord le <a href="http://o.mengue.free.fr/blog/2007/08/02/32-une-carte-des-stations-velib-sur-nokia-n800">post précédent</a> comme introduction.</strong></p>
<p>Voici le script pour Windows <code>stations2mm.cmd</code> :</p>
<pre class="code vim vimft-dosbatch">
@<span class="Identifier">echo</span><span class="Operator"> off</span>
xsltproc -o <span class="Identifier">%~dpn1</span>.sql <span class="Identifier">%~dpn0</span>.xslt <span class="Identifier">%1</span> || <span class="Statement">goto</span><span class="Label"> :EOF</span>
<span class="Statement">if</span><span class="Operator"> exist</span> velib-poi.db <span class="Identifier">del</span> velib-poi.db
<span class="Identifier">echo</span><span class="Constant"> .q</span>| sqlite3 -batch -init <span class="Identifier">%~dpn1</span>.sql velib-poi.db
</pre>
<p>Pour le lancer :</p>
<pre class="terminal cmd">
<samp class="prompt">C:\Users\Moi\Documents\Vélib'></samp><kbd>stations2mm stations.xml</kbd>
</pre>
<p>Voici la nouvelle feuille de style <code>stations2mm.xslt</code>. Le nombre de lignes a doublé simplement pour l'échappement correct des apostrophes.</p>
<pre class="code vim vimft-xslt">
<span class="Comment"><?</span><span class="Type">xml</span><span class="Type"> </span><span class="Type">version</span>=<span class="Constant">"1.0"</span><span class="Type"> </span><span class="Type">encoding</span>=<span class="Constant">"UTF-8"</span><span class="Comment">?></span>
<span class="Comment"><!</span><span class="Comment">-- stations2mm.xslt --</span><span class="Comment">></span>
<span class="Comment"><!</span><span class="Comment">-- Copyright (c) 2007 Olivier Mengué <a href="http://o.mengue.free.fr/">http://o.mengue.free.fr/</a> --</span><span class="Comment">></span>
<span class="Comment"><!</span><span class="Comment">--</span>
<span class="Comment"> Maemo Mapper POI format: <a href="http://eko.one.pl/index.php?page=Nokia770_software#Details">http://eko.one.pl/index.php?page=Nokia770_software#Details</a></span>
<span class="Comment">--</span><span class="Comment">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">stylesheet</span><span class="Identifier"> </span><span class="Type">version</span>=<span class="Constant">"1.0"</span><span class="Identifier"> </span><span class="Type">xmlns</span><span class="Comment">:</span><span class="Type">xsl</span>=<span class="Constant">"<a href="http://www.w3.org/1999/XSL/Transform">http://www.w3.org/1999/XSL/Transform</a>"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">output</span><span class="Identifier"> </span><span class="Type">method</span>=<span class="Constant">"text"</span><span class="Identifier"> </span><span class="Type">encoding</span>=<span class="Constant">"UTF-8"</span><span class="Identifier"> /></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">strip-space</span><span class="Identifier"> </span><span class="Type">elements</span>=<span class="Constant">"*"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Identifier"> </span><span class="Type">match</span>=<span class="Constant">"/markers"</span><span class="Identifier">></span>-- Script SQLite pour construire une base POI des stations Vélib pour Maemo
-- Mapper <a href="http://gnuite.com:8080/nokia770/maemo-mapper/">http://gnuite.com:8080/nokia770/maemo-mapper/</a> (Nokia 770, N800).
-- See <a href="http://eko.one.pl/index.php?page=Nokia770_software#Details">http://eko.one.pl/index.php?page=Nokia770_software#Details</a>
--
-- Créé avec stations2mm.xslt (<a href="http://o.mengue.free.fr/)">http://o.mengue.free.fr/)</a>
--
-- Pour céer le fichier:
-- echo .q | sqlite3 -batch -init stations.sql poi.db
PRAGMA encoding = "UTF-8";
CREATE TABLE IF NOT EXISTS category (cat_id INTEGER PRIMARY KEY, label TEXT NOT NULL, desc TEXT, enabled INTEGER NOT NULL);
CREATE TABLE IF NOT EXISTS poi (poi_id INTEGER PRIMARY KEY, lat REAL NOT NULL, lon REAL NOT NULL, label TEXT NOT NULL, desc TEXT, cat_id INTEGER NOT NULL);
CREATE INDEX IF NOT EXISTS poi_idx_latlon ON poi (lat ASC, lon ASC);
-- Placez 'Velib.jpg' dans un sous-répertoire 'poi' de votre dépôt de cartes
-- Pas d'accent dans label
INSERT INTO category (cat_id, label, desc, enabled) VALUES (30001, 'Velib', 'Station Vélib''', 1);
INSERT INTO category (cat_id, label, desc, enabled) VALUES (30002, 'Velib2', 'Station Vélib'' corrigée', 1);
INSERT INTO category (cat_id, label, desc, enabled) VALUES (30003, 'Velib3', 'Station Vélib'' validée', 1);
INSERT INTO category (cat_id, label, desc, enabled) VALUES (30004, 'Velib4', 'Station Vélib'' erronée', 1);
<span class="Comment"><!</span><span class="Comment">--</span>
<span class="Comment">Ignore les stations dont les coordonnées ne sont pas définies</span>
<span class="Comment"> lat=27.1409733745, lng=-3.40456062425</span>
<span class="Comment">--</span><span class="Comment">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">for-each</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"marker[@lat!='27.1409733745']"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">sort</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"@lat"</span><span class="Identifier"> </span><span class="Type">data-type</span>=<span class="Constant">"number"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">sort</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"@lng"</span><span class="Identifier"> </span><span class="Type">data-type</span>=<span class="Constant">"number"</span><span class="Identifier">/></span><span class="Comment"><!</span><span class="Comment">--</span>
<span class="Comment"> --</span><span class="Comment">></span>INSERT INTO poi (poi_id, lat, lon, label, desc, cat_id) VALUES (<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"30000+position()"</span><span class="Identifier">/></span>, <span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"@lat"</span><span class="Identifier">/></span>, <span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"@lng"</span><span class="Identifier">/></span>, '<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"@number"</span><span class="Identifier">/></span>', '<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">call-template</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"globalReplace"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">with-param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"input"</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"@address"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">with-param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"search"</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"</span><span class="Type">&</span><span class="Statement">quot</span><span class="Type">;</span><span class="Constant">'</span><span class="Type">&</span><span class="Statement">quot</span><span class="Type">;</span><span class="Constant">"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">with-param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"replacement"</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"</span><span class="Type">&</span><span class="Statement">quot</span><span class="Type">;</span><span class="Constant">''</span><span class="Type">&</span><span class="Statement">quot</span><span class="Type">;</span><span class="Constant">"</span><span class="Identifier">/></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">call-template</span><span class="Identifier">></span>', 30001);
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">for-each</span><span class="Identifier">></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Identifier">></span>
<span class="Comment"><!</span><span class="Comment">-- Voir <a href="http://www.xml.com/pub/a/2002/06/05/transforming.html">http://www.xml.com/pub/a/2002/06/05/transforming.html</a> --</span><span class="Comment">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"globalReplace"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"input"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"search"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"replacement"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">choose</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">when</span><span class="Identifier"> </span><span class="Type">test</span>=<span class="Constant">"contains($input, $search)"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Identifier"> </span><span class="Type">select</span>=
<span class="Identifier"> </span><span class="Constant">"concat(substring-before($input, $search),</span>
<span class="Constant"> $replacement)"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">call-template</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"globalReplace"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">with-param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"input"</span>
<span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"substring-after($input, $search)"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">with-param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"search"</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"$search"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">with-param</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="Constant">"replacement"</span>
<span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"$replacement"</span><span class="Identifier">/></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">call-template</span><span class="Identifier">></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">when</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">otherwise</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Identifier"> </span><span class="Type">select</span>=<span class="Constant">"$input"</span><span class="Identifier">/></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">otherwise</span><span class="Identifier">></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">choose</span><span class="Identifier">></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Identifier">></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">stylesheet</span><span class="Identifier">></span>
</pre>
Une carte des stations Vélib’ sur Nokia N800
urn:md5:9a8a308a1b23081a458724a88bdbdce7
2007-08-02T23:17:00+00:00
2011-06-05T21:12:20+00:00
Olivier Mengué
Code
cartecodeMaemoMaemo MappermapN800Nokia N800ParisPOIVélib'XSLT
<p><a href="http://www.velib.paris.fr/">Vélib’</a>, c'est génial ! Abonné depuis deux jours et déjà accro ! Vive le vélo Plug'n Play ! Vive le vélo jetable !</p>
<p>Néanmoins, un outils devient vite indispensable : la carte des stations.</p>
<p>Je suis l'heureux propriétaire d'un <a href="http://www.nokia.fr/A4363032">Nokia N800</a> : c'est une « tablette Internet », avec connexions wifi, Bluetooth et un écran 800x480. Le tout fonctionne avec un système ouvert : Linux. Et ça tient dans la poche.</p>
<p>Le logiciel <a href="http://gnuite.com:8080/nokia770/maemo-mapper/">Maemo Mapper</a> pour le N800 permet de télécharger des fonds de carte (Google Maps notamment) et de les afficher. Ces cartes peuvent aussi être récupérées dans un cache pour consultation hors-ligne. Ainsi on peut avoir tous les plans de Paris de Google Maps dans la poche, sans connexion Internet. Maemo Mapper peut aussi afficher les informations d'un GPS Bluetooth.</p>
<p>J'ai donc créé une base de points d'intérêt (POI) pour afficher les <a href="http://www.velib.paris.fr/les_stations/trouver_une_station">stations Vélib’</a> dans Maemo Mapper.</p>
<p>Mais ma source des données pour les emplacements des stations n'est pas libre : il s'agit du fichier XML publié sur le site officiel (http://www.velib.paris.fr/service/carto, voir <a href="http://www.gpspassion.com/forumsen/topic.asp?TOPIC_ID=56151&whichpage=4">ce forum</a>). Je préfère donc éviter de distribuer le fichier terminé. Je vais par contre vous expliquer comment recréer vous-même ce fichier.</p>
<p><img src="http://o.mengue.free.fr/dolmen.blog/public/DSCN4779-520.JPG" alt="Photo de mon N800 avec Maemo Mapper affichant un plan de Paris avec les stations Vélib'" height="310" width="520" /></p>
<p>Lisez <a href="http://o.mengue.free.fr/blog/2007/08/02/32-une-carte-des-stations-velib-sur-nokia-n800">la suite de ce post</a> pour voir le code...</p> <p><strong>Mise à jour : j'ai publié une <a href="http://o.mengue.free.fr/blog/2007/08/12/36-stations-velib-v20">v2.0</a>.</strong> Mais lisez d'abord ce post.</p>
<p>Voici les outils que j'ai utilisés :</p>
<ol>
<li><a href="http://curl.haxx.se/">curl</a> pour récupérer le fichier XML des stations (mais vous pouvez simplement utiliser votre navigateur web)</li>
<li><a href="http://xmlsoft.org/XSLT/xsltproc2.html">xsltproc</a> pour transformer les données en script SQL. Sous Windows, il vous faut <code>xsltproc.exe</code>, <code>libxml2.dll</code>, <code>libxslt.dll</code>, <code>libexslt.dll</code>, <code>iconv.dll</code>, <code>zlib1.dll</code>, à piocher dans les <a href="http://www.zlatkovic.com/pub/libxml/">divers zips</a>.</li>
<li><a href="http://www.sqlite.org/">sqlite3</a> pour créer la base de POI. Téléchargez les "Precompiled binaries For Windows" <a href="http://www.sqlite.org/download.html">ici</a>.</li>
</ol>
<p>Pour transformer les données des stations, j'utilise une transformation <a href="http://fr.wikipedia.org/wiki/Extensible_Stylesheet_Language_Transformations">XSLT</a> :</p>
<pre class="code vim vimft-xslt"><span class="Comment"><?</span><span class="Type">xml</span><span class="Type">version</span>=<span class="Constant">"1.0"</span><span class="Type">encoding</span>=<span class="Constant">"UTF-8"</span><span class="Comment">?></span>
<span class="Comment"><!--
stations2mm.xslt
Copyright © 2007 Olivier Mengué <a href="http://o.mengue.free.fr/">http://o.mengue.free.fr/</a>
Maemo Mapper POI format: <a href="http://eko.one.pl/index.php?page=Nokia770_software#Details">http://eko.one.pl/index.php?page=Nokia770_software#Details</a>
--></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">stylesheet</span><span class="Type">version</span>=<span class="Constant">"1.0"</span><span class="Type">xmlns</span><span class="Comment">:</span><span class="Type">xsl</span>=<span class="Constant">"<a href="http://www.w3.org/1999/XSL/Transform">http://www.w3.org/1999/XSL/Transform</a>"</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">output</span><span class="Type">method</span>=<span class="Constant">"text"</span><span class="Type">encoding</span>=<span class="Constant">"UTF-8"</span><span class="Identifier"> /></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">strip-space</span><span class="Type">elements</span>=<span class="Constant">"*"</span><span class="Identifier">/></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Type">match</span>=<span class="Constant">"/markers"</span><span class="Identifier">></span>-- Script SQLite pour construire une base POI des stations Vélib pour Maemo
-- Mapper <a href="http://gnuite.com:8080/nokia770/maemo-mapper/">http://gnuite.com:8080/nokia770/maemo-mapper/</a> (Nokia 770, N800).
-- See <a href="http://eko.one.pl/index.php?page=Nokia770_software#Details">http://eko.one.pl/index.php?page=Nokia770_software#Details</a>
--
-- Créé avec stations2mm.xslt (<a href="http://o.mengue.free.fr/%29">http://o.mengue.free.fr/</a>)
--
-- Pour céer le fichier:
-- sqlite3 -init velib.sql poi.db
PRAGMA encoding = "UTF-8";
CREATE TABLE IF NOT EXISTS poi (poi_id INTEGER PRIMARY KEY, lat REAL, lon REAL, label TEXT, desc TEXT, cat_id INTEGER);
CREATE TABLE IF NOT EXISTS category (cat_id INTEGER PRIMARY KEY, label TEXT, desc TEXT, enabled INTEGER);
-- Placez 'Velib.jpg' dans un sous-répertoire 'poi' de votre dépôt de cartes
INSERT INTO category (label, desc, enabled) VALUES ('Velib', NULL, 1);
<span class="Comment"><!</span><span class="Comment">--</span>
<span class="Comment">Ignore les stations dont les coordonnées ne sont pas définies</span>
<span class="Comment"> lat=27.1409733745, lng=-3.40456062425</span>
<span class="Comment">--</span><span class="Comment">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">apply-templates</span><span class="Type">select</span>=<span class="Constant">"marker[@lat!='27.1409733745']"</span><span class="Identifier">/></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Identifier">></span>
<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Type">match</span>=<span class="Constant">"marker"</span><span class="Identifier">></span>INSERT INTO poi (lat, lon, label, desc, cat_id) VALUES (<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Type">select</span>=<span class="Constant">"@lat"</span><span class="Identifier">/></span>, <span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Type">select</span>=<span class="Constant">"@lng"</span><span class="Identifier">/></span>, "VELIB <span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Type">select</span>=<span class="Constant">"@number"</span><span class="Identifier">/></span>", "<span class="Identifier"><</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">value-of</span><span class="Type">select</span>=<span class="Constant">"@address"</span><span class="Identifier">/></span>", 1);
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">template</span><span class="Identifier">></span>
<span class="Identifier"></</span><span class="Special">xsl</span><span class="Comment">:</span><span class="Statement">stylesheet</span><span class="Identifier">></span>
</pre>
<p>Voici les commandes à lancer :</p>
<pre class="terminal unix"><samp class="prompt shell">$ </samp><kbd class="shell">curl http://www.velib.paris.fr/service/carto > stations-velib.xml</kbd>
<samp class="prompt shell">$ </samp><kbd class="shell">xsltproc -o stations-velib.sql stations2mm.xslt stations-velib.xml</kbd>
<samp class="prompt shell">$ </samp><kbd class="shell">sqlite3 -init stations-velib.sql velib-poi.db</kbd>
<samp class="sqlite">Loading resources from stations-velib.sql
SQLite version 3.4.1
Enter ".help" for instructions</samp>
<samp class="prompt sqlite">sqlite> </samp><kbd class="sqlite sqlite3">.q</kbd>
</pre>
<p>Il suffit alors de transférer sur le N800 la base de données <code>velib-poi.db</code>. Dans le menu <em>Settings...</em>, onglet <em>POI</em>, sélectionnez enfin le chemin de votre <em>POI database</em>.</p>
<p>Pour afficher une icône spécifique comme symbole de station, placez une petite image JPEG nommée <code>Velib.jpg</code> (même nom que la catégorie) dans un sous-répertoire <code>poi</code> du répertoire de cache des fonds de carte.</p>
<p><strong>Mise à jour : j'ai publié une <a href="http://o.mengue.free.fr/blog/2007/08/12/36-stations-velib-v20">v2.0</a>.</strong></p>
Django aux Journées Perl 2006
urn:md5:9e4bbf25662d70635545a1e2d0a3f3d6
2006-11-25T09:20:48+00:00
2007-08-15T22:25:45+00:00
Olivier Mengué
Code
codeDjangoFPWfpw2006ORMPerlPython
<p>Hé oui, <a href="http://www.djangoproject.com/">Django</a> c'est du Python, et pourtant on j'en parlerais aux <a href="http://conferences.mongueurs.net/fpw2006/">Journées Perl 2006</a> ce week-end à la Cité des Sciences et de l'Industrie.</p>
<p>J'ai deux présentations au programme :</p>
<ul>
<li><a href="http://conferences.mongueurs.net/fpw2006/talk/424">14h00</a> <a href="http://o.mengue.free.fr/presentations/2006-fpw/intro-orm.html">Introduction aux ORM</a> : un introduction générale sur les ORM et une présentation du modèle de données utilisé en commun dans plusieurs des présentations : un mini modèle représentant une association de randonneurs.</li>
<li><a href="http://conferences.mongueurs.net/fpw2006/talk/424">14h10</a> <a href="http://o.mengue.free.fr/presentations/2006-fpw/django-models.html">Les modèles de Django</a> : une petite introduction générale sur Django puis l'accent sera mis sur la définition des modèles Django, l'API de requêtes et comment les spécificités de Python sont utilisées. L'objectif est de montrer un modèle de conception d'ORM et comment le sucre syntaxique du langage peut être mis à profit.</li>
</ul>
<p>Je vous invite à aller voir les autres présentations sur les ORMs qui ont lieu le <a href="http://conferences.mongueurs.net/fpw2006/schedule">samedi après-midi</a>.</p>