[Astro] #130 Bitmap to SVG Tracer — esm-potrace-wasm によるブラウザ完結型ラスタ→ベクタSVG変換ツール
概要
esm-potrace-wasm(Potrace の WebAssembly ビルド)を使って、PNG・JPEG・WebP 等のラスタ画像をサーバーにアップロードすることなくブラウザ内で完結してベクタ SVG に変換するツールを作りました。
Potrace はビットマップ画像を滑らかなベジェ曲線に変換するアルゴリズムで、Peter Selinger による C 実装がオリジナルです。esm-potrace-wasm はそれを Emscripten で WebAssembly にコンパイルし、ESM モジュールとしてブラウザで直接使えるようにしたものです。WASM バイナリは JS 内に base64 インラインされており、追加ファイルの配信が不要です。
GitHub - tomayac/esm-potrace-wasm
A modern ESM build of the Potrace library for use in the browser. WASM バイナリは JS に base64 インライン(76KB)。
github.com
Bitmap to SVG Tracer
ブラウザ完結型ラスタ→ベクタSVG変換ツール。PNG/JPEG/WebP等の画像をPotrace WASMでSVGに変換。
lain-lab.comスクリーンショット
カラーポスタライズ — SAMPLEロゴ画像(JPEG 12.5KB → SVG 100.9KB、825パス、16色、18ms)
カラーポスタライズ — VRM キャラクター画像(WebP 19.7KB → SVG 238.6KB、1797パス、37色、87ms)
動画(GIF)
技術構成
esm-potrace-wasm
npm パッケージ esm-potrace-wasm(v0.5.1)を使用。Potrace を Emscripten で WebAssembly にコンパイルしたもので、WASM バイナリは base64 エンコードされて JS ファイル(76KB)に内蔵されています。別途 .wasm ファイルを配信する必要がありません。
API は init() と potrace() の2メソッドのみ:
import { potrace, init } from 'esm-potrace-wasm';
// WASM 初期化(1回のみ)
await init();
// トレース実行
const svg = await potrace(imageBitmapSource, {
turdsize: 2, // ノイズ除去(小さい斑点を無視するサイズ)
turnpolicy: 4, // パス方向の解決方針(minority)
alphamax: 1, // コーナー閾値(0=鋭角、1.334=丸め最大)
opticurve: 1, // 曲線最適化の有効/無効
opttolerance: 0.2, // 曲線最適化の許容誤差
pathonly: false, // SVG全体 or パスデータのみ
extractcolors: true, // カラー抽出の有効/無効
posterizelevel: 6, // ポスタライズ階調数(1-255)
posterizationalgorithm: 1 // 0: simple, 1: interpolation
});
imageBitmapSource は HTMLImageElement・HTMLCanvasElement・ImageData・Blob 等を受け付けます。
Astro + Vite の設定
esm-potrace-wasm は WASM を base64 で JS に内蔵しているため、Web Worker 系のように optimizeDeps.exclude する必要はありません。Astro の <script> タグ内で直接 import するだけで動作します。
// src/pages/bitmap-to-svg.astro の <script> 内
import { potrace, init } from 'esm-potrace-wasm';
await init();
Vite がベアモジュール指定子を解決し、node_modules/esm-potrace-wasm/dist/index.js をバンドルします。
実装内容
基本フロー
ファイル選択 / ドラッグ&ドロップ
→ FileReader で DataURL 読み込み
→ Image 要素に描画
→ potrace(image, options) ← WASM 内で実行
→ SVG 文字列を取得
→ Compare 表示で Before/After 比較
→ SVG ダウンロード
2つのトレースモード
| モード | 説明 | 用途 |
|---|---|---|
| B/W Trace | 画像を白黒に二値化してからトレース | ロゴ・線画・シルエット |
| Color Posterize | 画像を複数の色階調に分割し、各階調をトレース | 写真・イラストのベクタ化 |
B/W モードでは extractcolors: false、posterizelevel: 2 に設定。Color モードでは extractcolors: true を有効にし、Posterize Level(1-10)で色の階調数を調整します。
Potrace パラメータ
全パラメータを UI から調整可能にしています。
| パラメータ | 説明 | 範囲 | デフォルト |
|---|---|---|---|
| Posterize Level | ポスタライズの階調数 | 1-10 | 6 |
| Turd Size | ノイズ除去閾値(指定サイズ以下の斑点を無視) | 0-100 | 2 |
| Alpha Max | コーナー閾値(小さいほど鋭角、大きいほど丸め) | 0-1.34 | 1.0 |
| Opt Tolerance | 曲線最適化の許容誤差 | 0-1 | 0.2 |
| Turn Policy | パス方向の解決方針 | black/white/left/right/minority/majority/random | minority |
| Optimize Curves | ベジェ曲線の最適化 | on/off | on |
| Extract Colors | カラー抽出 | on/off | on |
| Algorithm | ポスタライズアルゴリズム | Simple/Interpolation | Interpolation |
Compare 表示
中央のプレビューエリアは3つのタブで切り替え可能:
| タブ | 内容 |
|---|---|
| Compare | 左右分割で ORIGINAL と SVG を並べて比較 |
| Original | 入力画像のみ表示 |
| SVG | トレース結果の SVG のみ表示 |
SVG は白背景の <div> 内にインライン挿入しています。Astro の scoped CSS では動的に挿入される SVG 要素にスタイルが当たらないため、:global(svg) セレクタを使用しています。
.svg-preview :global(svg) {
max-width: 100%;
max-height: 100%;
}
SVG 情報パネル
右パネルには以下の情報を表示:
| 項目 | 説明 |
|---|---|
| SVG Size | 出力 SVG のバイトサイズ |
| Paths | SVG 内の <path> 要素数 |
| Dimensions | viewBox から取得した幅×高さ |
| Colors | SVG 内のユニーク fill カラー数 |
| Time | トレース処理にかかった時間(ms) |
| Compression | 入力画像との容量比較 |
カラーパレット抽出
SVG 出力からユニークな fill カラーを正規表現で抽出し、カラースウォッチとして表示します。スウォッチクリックで #rrggbb がクリップボードにコピーされます。
const colorMatches = [...svgResult.matchAll(/fill="#([a-fA-F0-9]{6})"/g)];
const uniqueColors = [...new Set(colorMatches.map(m => m[1]))];
機能一覧
| カテゴリ | 内容 |
|---|---|
| ベクタ変換 | Potrace WASM によるラスタ→ベクタ SVG 変換 |
| トレースモード | B/W Trace・Color Posterize の2モード |
| パラメータ調整 | Posterize Level・Turd Size・Alpha Max・Opt Tolerance・Turn Policy・Optimize Curves |
| Compare 表示 | Before/After 左右分割比較 |
| カラーパレット | SVG からユニーク色抽出・クリップボードコピー |
| SVG 情報 | サイズ・パス数・色数・処理時間・圧縮率 |
| SVG ダウンロード | 元ファイル名ベースの .svg ファイル保存 |
| ブラウザ完結 | サーバーへのアップロード不要 |
技術スタック
- esm-potrace-wasm v0.5.1 — Potrace の WebAssembly ビルド(WASM base64 インライン、76KB)
- Astro — ページビルド・スクリプトバンドル
- Canvas API — 画像データの取得(Potrace への入力)
Potrace について
Potrace(Polygon Tracer)は Peter Selinger が 2001 年に開発したビットマップトレースアルゴリズムです。入力のビットマップ画像からパスを抽出し、ベジェ曲線で近似した滑らかなベクタアウトラインを生成します。
Inkscape の「ビットマップをトレース」機能にも採用されている実績のあるアルゴリズムで、ライセンスは GPL-2.0 です。esm-potrace-wasm はオリジナルの C ソースを Emscripten で WASM にコンパイルしたもので、ブラウザ環境で同等の品質のトレースが可能です。
ポスタライズ機能は、画像を複数の階調レベルに量子化し、各レベルごとにトレースを実行して合成することで、カラー画像のベクタ化を実現しています。
WASM 未開拓リスト消化状況
今回で Potrace WASM が完了し、STEP Viewer のエッジ抽出(SVG 出力)の積み残しとも合流できる基盤が整いました。
| ライブラリ | ステータス |
|---|---|
| OpenCASCADE | ✅ STEP/IGES ビューア v2 |
| GDAL | ✅ gdal3.js |
| OpenJPEG | ✅ JP2 Converter |
| laz-perf | ✅ Point Cloud Viewer |
| Assimp | ✅ 3D Model Viewer |
| Photo Editor | ✅ WebGL シェーダー |
| libheif | ✅ HEIC/AVIF Converter |
| libraw | ✅ Camera RAW Viewer |
| Potrace | ✅ Bitmap to SVG Tracer ← 今回 |
| web-ifc | ✅ IFC ビューア |
| libarchive | ✅ Archive Manager |
今後の展開
- STEP Viewer エッジ抽出との合流 — STEP Viewer v2 のベクトルエッジ抽出(SVG 出力)の積み残しを、Potrace の SVG 出力パイプラインを応用して実装
- バッチ処理 — 複数画像の一括トレース・一括 SVG ダウンロード
- SVG 最適化 — 出力 SVG のパス数削減・ファイルサイズ最適化(SVGO 相当の処理)
- B/W モードの閾値調整 — 二値化の閾値をスライダーで調整し、プレビューに即時反映
更新履歴
- [v1.0] (2026-09-07): 初回公開。
- esm-potrace-wasm (v0.5.1) によるラスタ→ベクタ SVG 変換パイプライン構築
- B/W Trace・Color Posterize の2モード対応
- 全 Potrace パラメータの UI 調整(Posterize Level / Turd Size / Alpha Max / Opt Tolerance / Turn Policy / Optimize Curves / Extract Colors / Algorithm)
- Compare 表示(Before/After 左右分割比較)
- SVG 情報パネル(サイズ・パス数・色数・処理時間・圧縮率)
- カラーパレット抽出・クリップボードコピー
- SVG ダウンロード