2012年7月2日月曜日

ブラウザ上でラスタ画像をsvgに変換するの続き

この前公開したスクリプトの処理がいかにも遅いので,コードを弄って処理を高速化した所,凡そ処理時間を3分の1に短縮することができました.元のコードの出来が良かったので,高速化そのものはそれほど難しくなかったものの,ここまで違うものかと改めて驚いていたり.
つづき

オリジナル版でもいろいろ遊べますが,このpotrace.js私家版では機能の修正・追加を行いました.相変わらず中身の処理は理解していませんが.
  • 処理速度を改善した.(何とか使える程度には)
  • パス精度パラメータの追加.
  • パス文字列をsvg準拠のものに変更.
  • 直接SVGPathElementを取得するメソッドを追加.
  • 単一のPathElementとするか断片毎にPathElementを生成するかを選択可能とした.
  • オリジナル版のバグを修正した.widthとheightが異なる値の場合に上手く動作しない.  
  • 2012/07/04 真っ白なsvgを生成した際にd属性が不正となる部分を修正.
なおcanvasに書き込む機能は有していません.パス文字列を解析すればオリジナル版と同様に処理できるはず(メリットはよくわからないけれど).
canvasを使っているので,処理と画像のドメインが異なるとセキュリティエラーとなります.ローカル環境においてもブラウザ設定によってはエラーになるかもしれません

動作環境:svgとcanvas要素が使えるブラウザ.firefox,chrome,operaでは動作を確認.
potrace.js私家版
potrace-packed.js/packer/で圧縮したもの)

ライセンスはGPL2になりますんで,その部分ご注意を.煮るなり焼くなりご勝手に.
コードはas-isで提供されます.

使い方については下記サンプルを参照のこと.
  •  画像を単一のpath要素として取得する場合.


<!DOCTYPE html>
<html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
 <style type="text/css">
img,svg{
 float:left;
}
 </style>
 <script type="text/javascript" src="potrace-packed.js"></script>
 <script type="text/javascript">
window.onload = function(){
 
 setTimeout(function(){
  var start = new Date();
  main();
  var end = new Date();
  var div = document.createElement("div");
  div.innerHTML = (end.getTime() - start.getTime()) + "ms";
  div.style.position = "absolute";
  document.getElementsByTagName("body")[0].appendChild(div);
 }, 0);

 function main(){
  //img要素を取得する.
  var img = document.getElementById("img");
  var width = img.width;
  var height = img.height;
 
  //svg要素を生成する.
  var svg = document.getElementById("svg");
  svg.setAttribute("width", width);
  svg.setAttribute("height", height);
  svg.setAttribute("viewBox", [0,0,width,height].join(" "));

  //階調毎にパスを重ねていく.
  appendPath(svg, getPathElem(img, 0.9), "#ff9");
  appendPath(svg, getPathElem(img, 0.8), "#ee6");
  appendPath(svg, getPathElem(img, 0.5), "#bb3");
  appendPath(svg, getPathElem(img, 0.46), "#440");
  appendPath(svg, getPathElem(img, 0.3), "#000");

  function getPathElem(img, threshold){
   //Potraceにパラメータを設定する.
   //※パラメータの詳細な意味はよく判っていない…
   Potrace.setParam({
    threshold: threshold,
    turdSize:3,
    turnPolicy:1,
    alphamax:0.9,
    precision:1
   });
 
   //パス文字列を取得する.
   var pathElem = Potrace.trace(img).toPathElement();
   return pathElem;
  }
  function appendPath(svg, pathElem, fill){
   pathElem.setAttribute("fill", fill);
   svg.appendChild(pathElem);
  }
 }
};
 </script>
 </head>
 <body>
 <img id="img" src="nc943.png" width="350" height="350"></img>
 <svg id="svg">
 </svg>
 </body>
</html>
  • 画像を複数のpathに分解する場合.
    path群はg要素でグループ化されます. path毎にodd/evenのclassが付与されるので,これを使って色を設定することができます.pathは描画順に並んでいます.画像のアウトラインを抽出するのに使えます.


<!DOCTYPE html>
<html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
 <style type="text/css">
img,svg{
 float:left;
}
img#img{
 display:none;
}
svg{
 width:350px;
 height:350px;
}
g>path.even{
 fill:yellow;
}
g>path.odd{
 fill:blue;
}
 </style>
 <script type="text/javascript" src="potrace-packed.js"></script>
 <script type="text/javascript">
window.onload = function(){
 
 setTimeout(function(){
  var start = new Date();
  main();
  var end = new Date();
  var div = document.createElement("div");
  div.innerHTML = (end.getTime() - start.getTime()) + "ms";
  div.style.position = "absolute";
  document.getElementsByTagName("body")[0].appendChild(div);
 }, 0);

 function main(){
  //img要素を取得する.
  var img = document.getElementById("img");
  var width = img.width;
  var height = img.height;
 
  //svg要素を生成する.
  var svg = document.getElementById("svg");
  svg.setAttribute("width", width);
  svg.setAttribute("height", height);
  svg.setAttribute("viewBox", [0,0,width,height].join(" "));

  //Potraceにパラメータを設定する.
  //※パラメータの詳細な意味はよく判っていない…
  Potrace.setParam({
   threshold: 0.5,
   turdSize:3,
   turnPolicy:1,
   alphamax:0.9,
   precision:2
  });

  var gElem = Potrace.trace(img).toPathElements();
  svg.appendChild(gElem);
 }
};
 </script>
 </head>
 <body>
 <img src="nc1123.png" width="350" height="350"></img>
 <img id="img" src="nc1123.png" width="500" height="500"></img>
 <svg id="svg">
 </svg>
 </body>
</html>
  • path文字列を取得したい場合は,traceメソッドを実行した後,outpathメソッドを実行して下さい.
  • パラメータのprecision値はpath文字列の小数点以下の精度桁数です.0で整数値となります.-1で丸め無しとなります.

0 件のコメント:

コメントを投稿