[Astro] #130 Bitmap to SVG Tracer — esm-potrace-wasm によるブラウザ完結型ラスタ→ベクタSVG変換ツール

[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 インラインされており、追加ファイルの配信が不要です。

スクリーンショット

カラーポスタライズ — SAMPLEロゴ画像(JPEG 12.5KB → SVG 100.9KB、825パス、16色、18ms)

Bitmap to SVG Tracer — SAMPLEロゴのカラーポスタライズ結果

カラーポスタライズ — VRM キャラクター画像(WebP 19.7KB → SVG 238.6KB、1797パス、37色、87ms)

Bitmap to SVG Tracer — VRMキャラクターのカラーポスタライズ結果 Bitmap to SVG Tracer — VRMキャラクターのカラーポスタライズ結果

動画(GIF)

Bitmap to SVG Tracer — SAMPLEロゴのカラーポスタライズ結果

技術構成

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
});

imageBitmapSourceHTMLImageElementHTMLCanvasElementImageDataBlob 等を受け付けます。

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: falseposterizelevel: 2 に設定。Color モードでは extractcolors: true を有効にし、Posterize Level(1-10)で色の階調数を調整します。

Potrace パラメータ

全パラメータを UI から調整可能にしています。

パラメータ説明範囲デフォルト
Posterize Levelポスタライズの階調数1-106
Turd Sizeノイズ除去閾値(指定サイズ以下の斑点を無視)0-1002
Alpha Maxコーナー閾値(小さいほど鋭角、大きいほど丸め)0-1.341.0
Opt Tolerance曲線最適化の許容誤差0-10.2
Turn Policyパス方向の解決方針black/white/left/right/minority/majority/randomminority
Optimize Curvesベジェ曲線の最適化on/offon
Extract Colorsカラー抽出on/offon
AlgorithmポスタライズアルゴリズムSimple/InterpolationInterpolation

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 のバイトサイズ
PathsSVG 内の <path> 要素数
DimensionsviewBox から取得した幅×高さ
ColorsSVG 内のユニーク 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 ダウンロード