{"id":2177,"date":"2009-04-03T23:55:00","date_gmt":"2009-04-03T23:55:00","guid":{"rendered":"http:\/\/svay.com\/blog\/?p=2177"},"modified":"2017-05-29T20:58:52","modified_gmt":"2017-05-29T18:58:52","slug":"generer-des-anaglyphes-avec-javascript-et-canvas","status":"publish","type":"post","link":"https:\/\/svay.com\/blog\/generer-des-anaglyphes-avec-javascript-et-canvas\/","title":{"rendered":"G\u00e9n\u00e9rer des anaglyphes avec javascript et canvas"},"content":{"rendered":"<p>Il n&#8217;y a pas tr\u00e8s longtemps, j&#8217;ai trouv\u00e9 des lunettes 3D sur une bo\u00eete de Chocapics. Ca m&#8217;a rappel\u00e9 les essais d&#8217;images en 3D que je faisais il y a quelques ann\u00e9es. La recette est super simple: on prend deux images, une pour l&#8217;oeil gauche et l&#8217;autre pour l&#8217;oeil droit. De l&#8217;une, on prend la composante rouge et de l&#8217;autre, la composante cyan (bleu+vert). On m\u00e9lange le tout et&#8230; paf! Ca fait un <a href=\"http:\/\/fr.wikipedia.org\/wiki\/Anaglyphe\" hreflang=\"fr\">anaglyphe<\/a>!<\/p>\n<p>Ayant jou\u00e9 r\u00e9cemment avec Javascript et l&#8217;\u00e9l\u00e9ment <a href=\"http:\/\/www.w3.org\/TR\/html5\/the-canvas-element.html#the-canvas-element\" hreflang=\"en\">canvas<\/a>, je me suis dit que \u00e7a pourrait se faire facilement avec ces deux technologies. Apr\u00e8s quelques essais, j&#8217;ai obtenu un <a href=\"\/experiences\/canvas-anaglyph\/\" hreflang=\"en\">Anaglyph generator<\/a> qui fonctionne \u00e0 peu pr\u00e8s avec un Firefox, un Safari ou un Opera r\u00e9cent. Concernant Internet Explorer, aucune chance pour le moment: <a href=\"http:\/\/code.google.com\/p\/explorercanvas\/\" hreflang=\"en\">excanvas<\/a> ne supporte pas encore <code>getImageData<\/code> ni <code>putImageData<\/code>.<\/p>\n<p>Pour g\u00e9n\u00e9rer un anaglyphe, il suffit d&#8217;indiquer deux URLs d&#8217;images et de presser le bouton. Pour simplifier, le resultat est toujours affich\u00e9 en 640&#215;480 (N&#8217;h\u00e9sitez pas \u00e0 poster l&#8217;URL de votre anaglyphe dans les commentaires!).<\/p>\n<p><img decoding=\"async\" style=\"display: block; margin: 0 auto;\" title=\"Exemple d'anaglyphe\" src=\"\/blog\/public\/images\/2009-04-03\/anaglyphe.jpg\" alt=\"Anaglyphe\" \/><\/p>\n<p>Ceux que \u00e7a int\u00e9resse, peuvent jeter un oeil au code. C&#8217;est plut\u00f4t simple:<\/p>\n<ul>\n<li>on charge deux images;<\/li>\n<li>on attend qu&#8217;elles soient compl\u00e8tement charg\u00e9es;<\/li>\n<li>on cr\u00e9e deux canvas pour y copier les images;<\/li>\n<li>on remplace la composante rouge d&#8217;un canvas par la composante rouge de l&#8217;autre;<\/li>\n<li>et on affiche le r\u00e9sultat!<\/li>\n<\/ul>\n<h3>Les pi\u00e8ges \u00e0 \u00e9viter<\/h3>\n<p>M\u00eame si la technique est simple, il y&#8217;a tout de m\u00eame quelques pi\u00e8ges \u00e0 contourner.<\/p>\n<p>Le premier est la politique de s\u00e9curit\u00e9 du navigateur. Comme pour les requ\u00eates XMLHttpRequest, le navigateur ne permet d&#8217;acc\u00e9der aux pixel que des images du m\u00eame domaine. Du coup, pour pouvoir afficher une image venant d&#8217;ailleurs, il faut passer un proxy.<\/p>\n<p>Voil\u00e0 \u00e0 quoi ressemble le proxy:<\/p>\n<pre> &lt;?php if (isset($_GET['url']) &amp;&amp; preg_match('\/^http\/i', $_GET['url'])) {     $url = $_GET['url'];     if (preg_match('\/.png$\/i', $url)) {         header('Content-type: image\/png');     }elseif (preg_match('\/.jpg$\/i', $url)) {         header('Content-type: image\/jpg');     }     readfile($url); }<\/pre>\n<p>Le second, est qu&#8217;il faut s&#8217;assurer que les images sont bien charg\u00e9es. En local, \u00e7a va forc\u00e9ment tr\u00e8s vite et on n&#8217;a jamais de probl\u00e8me. Avec des images distantes, \u00e7a peut mettre un peu de temps et emp\u00eacher le script de fonctionner. Pour r\u00e9soudre ce probl\u00e8me, deux trucs:<\/p>\n<ul>\n<li>utiliser setTimeout pour attendre en boucle que les images soient charg\u00e9es. La fonction <code>Anaglyph.wait<\/code> v\u00e9rifie si les images sont totalement charg\u00e9e en regardant l&#8217;attribut <code>complete<\/code>. Si ce n&#8217;est pas le cas, elle va attendre un peu et s&#8217;appeler elle-m\u00eame \u00e0 nouveau. Une fois que les deux images sont charg\u00e9es, elle peut appeler <code>Anaglyph.make<\/code> qui va g\u00e9n\u00e9rer l&#8217;anaglyphe.<\/li>\n<li>imbriquer le code qui manipules les canvas dans un <code>try\/catch<\/code> pour \u00e9viter que le code ne casse.<\/li>\n<\/ul>\n<p>Si l&#8217;\u00e9l\u00e9ment canvas vous int\u00e9resse, il y&#8217;a d\u00e9j\u00e0 pas mal de ressources int\u00e9ressantes sur le sujet:<\/p>\n<ul>\n<li><a href=\"https:\/\/developer.mozilla.org\/en\/HTML\/Canvas\" hreflang=\"en\">L&#8217;\u00e9l\u00e9ment Canvas sur DevMo<\/a><\/li>\n<li><a href=\"http:\/\/dev.opera.com\/articles\/javascript\/\" hreflang=\"en\">Les articles de Dev.Opera sur Javascript<\/a><\/li>\n<\/ul>\n<p>Plein de choses int\u00e9ressantes ont d\u00e9j\u00e0 \u00e9t\u00e9 faites avec canvas: de la 3D, de la visualisation de musique, de la retouche d&#8217;images, des trucages vid\u00e9os, etc. Il y&#8217;a s\u00fbrement encore plein d&#8217;autres choses \u00e0 faire. De quoi me faire r\u00e9fl\u00e9chir toute la nuit encore&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Il n&#8217;y a pas tr\u00e8s longtemps, j&#8217;ai trouv\u00e9 des lunettes 3D sur une bo\u00eete de Chocapics. Ca m&#8217;a rappel\u00e9 les essais d&#8217;images en 3D que je faisais il y a quelques ann\u00e9es. La recette est super simple: on prend deux images, une pour l&#8217;oeil gauche et l&#8217;autre pour l&#8217;oeil droit. De l&#8217;une, on prend la [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[21],"tags":[],"_links":{"self":[{"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/posts\/2177"}],"collection":[{"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/comments?post=2177"}],"version-history":[{"count":1,"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/posts\/2177\/revisions"}],"predecessor-version":[{"id":2572,"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/posts\/2177\/revisions\/2572"}],"wp:attachment":[{"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/media?parent=2177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/categories?post=2177"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/svay.com\/blog\/wp-json\/wp\/v2\/tags?post=2177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}