svg2png-wasmをつくった
つくったもの
svg2png-wasm
という名前に全ての情報が入っていますが、 WebAssembly を内部で利用して SVG 画像を PNG 画像に変換することができます。
つくった経緯
SVG のメリット
SVG は XML で記述されるベクター画像ですが、以下のような利点があると考えています。
- ベクター画像なため拡大してもドットが見えてこない
- 文字列で構築できるので(文字や図形を中心とした画像を)非常に低いコストで動的に生成できる
- Markdown で記述されたドキュメント内で表示できる(ついでにアニメーションできる)
よく見るこれも SVG
svg2png-wasm のアイコンも SVG
SVG のデメリット
動的に生成しやすいとなると OGP の画像に設定したくなります(なります)。
ですが、そうは問屋がおろしません。
Facebook のドキュメントによれば、JPEG
, GIF
, PNG
が設定できるようです。
このように、SVG はラスター画像しか設定できないシーンにおいてはかなり都合が悪かったりします。
そこで、SVG を PNG に変換したくなってきます。
svg2png-wasm 以外のソリューション
SVG を PNG に変換するというのはよくある話で、すでに多くのソリューションが存在します。
JavaScript を用いた場合でも以下のようなものが挙げられます。
- ブラウザ(Puppeteer や Playwright)を立ち上げるタイプ
- SVG を表示してスクリーンショットを撮る
- canvas 上に描画する
- Node.js 上で完結するタイプ
- canvas 互換のライブラリを用いて描画する
- ネイティブライブラリを Node-API(N-API)で呼び出す
種類こそあるものの、ブラウザやネイティブライブラリは OS などの環境に依存してしまいます。
また、ブラウザを立ち上げるものは、描画は正確ですが、速度はあまりでないと思います(要検証)。
そこで WebAssembly を用い環境に依存せず、高速に変換できればと考えました。
(というかすでに類似のライブラリがありました。があまり整備されていない印象を受けたので目を瞑りイチから作りました)
技術的な部分
SVG から PNG への変換には resvg という MPL-2.0 でライセンスされたライブラリを使っています。
これを wasm-bindgenを用いて WebAssembly に変換しています。
WASM そのままでは取り回しが悪いため wasm-packを用いることで JavaScript の薄いラッパーと TypeScript の型を生成してくれます。
ですが、まだ取り回しが悪かったのでさらに TypeScript でラップしました。
バンドルには esbuild を用いています。
動くもの
一番上に貼ったリンクを再掲しますが、デモサイトを作りました。
ブラウザ上(Web Worker)で動くサンプルをご覧いただけます。
また、Deno Deploy で動作するものも暫定的に(Deno Deploy が Beta なので)作ってあります。
こちらはリポジトリをご覧ください。
2021/10/18 追記:
Cloudflare Workers で動くものも更新しました。
内容としては Deno Deploy とほぼ同じです。
追記ここまで
こちらは動いていないのですが、OGP 生成を行うプロダクトにハッカソンで組み込んでみることもやってみました。
もしよければ併せてご覧ください。
ライセンス
先に紹介した resvg というライブラリですが、MPL-2.0 でライセンスされています。
このライブラリを利用しているライブラリは準コピーレフトという理由からか MPL-2.0 でライセンスされているのが散見されました。
個人的には svg2png-wasm は MIT ライセンスで頒布したいと考えており、そもそも可能なのか分からず、
ライセンスと睨めっこしたり OSS ライセンスの教科書 という本を読んでみたりしましたが結局わからなかったので、 resvg 作者に聞いたところ、
Good question. I don't know actually.
いい質問だね。正直知らないんだよね(意訳)
と言われましたが、認識自体は概ね一致していたので MIT ライセンスで頒布をしています。(法律やライセンスに造詣の深い方はアドバイスをください…)
MPL-2.0 よりは使いやすいと思うのでどんどん使ってください。
おわりに
バグや、おかしなところ、要望があればIssuesかDiscussionsへお願いします!
Discussion