svg2png-wasm

https://github.com/ssssota/svg2png-wasm

TypeScript

JavaScript

SVG画像をPNG画像に変換するライブラリ

Sotaro Tommykawa

推しアイデア

WASMを利用することで高速かつ安全に様々な環境で変換ができる

作った背景

一般にSVGからPNGの変換にはネイティブライブラリが絡むことが多く、体験は良好とは言えなかった。これを改善するためにWASMを用いたライブラリとして作成した

推し技術

wasm_bindgen, WASMはもうすぐデファクトになると思います

プロジェクト詳細

svg2png-wasm

これは、SVG画像をPNG画像に変換するためのライブラリです。wasmとはWebAssemblyの略で安全性や速度に注目が集まっている技術です。

前提

SVGからPNGを生成するモチベーション

SVGとは、XMLを用いたベクター画像形式です。 これが意味するところは、

  • ベクター画像であるがために、拡大、縮小を柔軟に行え、拡大してもドットが見えてこないこと
  • XMLであるがために、内部はテキストであり、非常に低いコストで柔軟に画像を生成できる

といったところです。 つまり、「簡単に生成でき、使い勝手がいい」という風に考えています。(あくまでも私個人の意見です)

対して、SNSなどでみる画像や、所謂写真と呼ばれるものはPNGやJPGといったピクセル画像が多く、聞き馴染みもあると思います。 これは風景や人など私たちが普段見ているものをベクター画像で表現することが非常に難しいためだと思います。

このように、SVGは簡単に生成でき、PNGが普及しているという状況下で「SVGをPNGに変換する」というのは必然に近いと考えています。 (もちろん風景や人物をSVGで描画するというものではなく、図形や文字で構成された画像を中心に考えています)

WASMを用いた理由

一般に、SVGからPNGへの変換には以下のような技術が用いられます。

  • Puppeteerなどのブラウザを介したキャプチャ
  • Web Canvas技術を用いた描画

このような技術は、ブラウザなどで培われた技術の恩恵を全面に享受できるので確実な選択だと思います。

一方で、昨今では、Cloudflare Workersを代表としたCDNエッジなどで動作する環境が増え、このような環境では、上記の技術では不足が生えると考えています。

具体的には、

  • ネイティブライブラリへの依存による環境の限定
  • CDNエッジではネイティブライブラリが確実に存在する保証はありませんし、独自に導入することも難しいでしょう
  • CPU計算時間への制限
  • ブラウザに依存する場合、ブラウザの起動などのオーバーヘッドにより、ギリギリもしくは間に合わないケースがほとんどになると思います(未検証)

このような環境でより柔軟に動作させることができればということでWASMを用いた開発に踏み切りました。

技術

  • Rust
  • wasm_bindgen
  • WebAssemble
  • TypeScript
  • Rollup
  • Jest

(処理順)

バンドルまで

Rust製のMPL-2.0ライブラリ resvg を用いてコアとなる機能を作成し、 wasm_bindgenを用いることでWebAssemblyを生成しています。

TypeScriptでラップした後、Rollupをバンドラとして採用することで、Node.js, Deno, ブラウザから呼び出しやすい形にバンドルして、簡単に導入できるような体制を作りました。

リリース

Jestで起動と簡単な動作確認を行うと同時に、簡単なSVGを用いてビジュアルリグレッションテストも行うことでデグレードを防いでいます。

Sotaro Tommykawa

@ssssota