SVGcode: ラスター画像を SVG ベクター グラフィックに変換する PWA

SVGcode は、JPG、PNG、GIF、WebP、AVIF などのラスター画像を SVG 形式のベクター グラフィックに変換できるプログレッシブ ウェブアプリです。File System Access API、Async Clipboard API、File Handling API、Window Controls Overlay のカスタマイズを使用します。

で確認できます。 <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> (読むより動画の方がよい場合は、この記事を動画でもご覧いただけます)。

ラスターからベクターへ

画像を拡大したときに、モザイク状になって満足のいく結果が得られなかったことはありますか?条件 WebP、PNG、JPG などのラスター画像形式を使用したこともあるでしょう。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> ラスター画像を拡大すると、モザイク状になります。

これに対して、ベクター グラフィックは、座標系上の点によって定義される画像です。これらの 点が線と曲線で結ばれ、多角形などの図形を形成します。ベクター グラフィックには、 任意の解像度にスケールアップまたはスケールダウンできる点で、ラスター グラフィックよりも優れている できます。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 品質を損なわずにベクター画像をスケールアップする。

SVGcode の概要

ラスター画像を SVGcode という PWA に 説明します。クレジットの期限: 自分で作成したものではない。SVGcode を使用すると、 Potrace というコマンドライン ツールのショルダーを Peter Selinger 氏 Web Assembly に変換されたため、 ウェブアプリ。

<ph type="x-smartling-placeholder">
</ph> SVGcode アプリケーションのスクリーンショット。 <ph type="x-smartling-placeholder">
</ph> SVGcode アプリ。

SVGcode の使用

まず、アプリの使い方をご紹介します。Chrome Dev Summit のティーザー画像から開始 ChromiumDev の Twitter チャンネルからダウンロードしたコードです。これは PNG ラスター画像で SVGcode アプリに移動しますファイルをドロップすると、アプリが画像を色ごとにトレースします。 入力がベクトル化された形式で返されます。画像にズームインします シャープですしかし Chrome ロゴを拡大して見ると トレースが正しく実行されていないことがわかります 特にロゴの輪郭が少しぼやけているように見えるでしょう。結果を改善するために、 たとえば 5 ピクセルまでのスペックルを抑制します。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> ドロップした画像を SVG に変換する。

SVGcode でのポスター化

ベクトル化(特に写真画像の場合)の重要なステップは、入力のポスター化です。 色の数を減らします。SVGcode を使うと、これをカラーチャネルごとに行うことができます。 結果的に SVG が出力されます。結果に満足したら、SVG をハードディスクに保存できます。 いつでもどこでも使えます

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 画像をポスタライズして色数を減らす。

SVGcode で使用する API

ここまででアプリの機能を確認できました。次に、アプリの実行に役立つ API をいくつか紹介します。 魔法のようなことが起こります。

プログレッシブ ウェブアプリ

SVGcode はインストール可能なプログレッシブ ウェブアプリであるため、完全にオフラインが可能です。このアプリは 日付 Vanilla JS テンプレート Vite.js 用で、一般的な Vite プラグイン PWA: 内部で Workbox.js を使用します。ワークボックスは プログレッシブ ウェブアプリ用の本番環境用 Service Worker を強化するライブラリの すべてのアプリで機能するとは限りませんが、SVGcode のユースケースには最適です。

ウィンドウ コントロール オーバーレイ

SVGcode では、使用可能な画面スペースを最大限活用するために ウィンドウ コントロール オーバーレイのカスタマイズ。メインメニューを上に移動します。 クリックします。インストール フローの最後に、この機能が有効になります。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> SVGcode をインストールし、ウィンドウ コントロール オーバーレイのカスタマイズを有効にする

File System Access API

入力画像ファイルを開き、生成された SVG を保存するには、 File System Access API。これにより、以前のリソースへの参照を保持できます。 アプリを再読み込みした後も、前回中断したところから再開できます。画像がアップロードされるたびに、 svgo ライブラリを介して最適化されます。これには少し時間がかかる場合があります。 SVG の複雑さにもよりますファイル保存ダイアログを表示するには、ユーザー操作が必要です。内容 そのため、SVG 最適化が行われる前にファイル ハンドルを取得することが重要になります。 最適化された SVG の準備が整うまでに操作が無効にならない。

try {
  let svg = svgOutput.innerHTML;
  let handle = null;
  // To not consume the user gesture obtain the handle before preparing the
  // blob, which may take longer.
  if (supported) {
    handle = await showSaveFilePicker({
      types: [{description: 'SVG file', accept: {'image/svg+xml': ['.svg']}}],
    });
  }
  showToast(i18n.t('optimizingSVG'), Infinity);
  svg = await optimizeSVG(svg);
  showToast(i18n.t('savedSVG'));
  const blob = new Blob([svg], {type: 'image/svg+xml'});
  await fileSave(blob, {description: 'SVG file'}, handle);
} catch (err) {
  console.error(err.name, err.message);
  showToast(err.message);
}

ドラッグ&ドロップ

入力画像を開くには、ファイルを開く機能を使用するか、前述のように アプリに画像ファイルをドラッグ&ドロップします。ファイルを開く機能はとても簡単で、 興味深いのはドラッグ&ドロップケースです特に便利な点は を介してデータ転送アイテムからファイル システムのハンドルを取得する getAsFileSystemHandle() メソッドを呼び出します。前述のように、このハンドルは保持できるので、アプリが再読み込みされたときに準備が整います。

document.addEventListener('drop', async (event) => {
  event.preventDefault();
  dropContainer.classList.remove('dropenter');
  const item = event.dataTransfer.items[0];
  if (item.kind === 'file') {
    inputImage.addEventListener(
      'load',
      () => {
        URL.revokeObjectURL(blobURL);
      },
      {once: true},
    );
    const handle = await item.getAsFileSystemHandle();
    if (handle.kind !== 'file') {
      return;
    }
    const file = await handle.getFile();
    const blobURL = URL.createObjectURL(file);
    inputImage.src = blobURL;
    await set(FILE_HANDLE, handle);
  }
});

詳しくは、File System Access API に関する記事をご覧ください。 興味のある方は、Google Cloud の SVGcode ソースコードを src/js/filesystem.js

Async Clipboard API

SVGcode は、Async Clipboard API を通じて、オペレーティング システムのクリップボードと完全に統合されています。 オペレーティング システムのファイル エクスプローラにある画像をアプリに貼り付けるには、 [画像を貼り付け] ボタンを使用するか、キーボードの command または Ctrl+V を押します。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> ファイル エクスプローラーから SVGcode に画像を貼り付けています。

Async Clipboard API では最近、SVG 画像も扱えるようになったため、 また、SVG 画像をコピーして別のアプリケーションに貼り付けてさらに処理することもできます。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> SVGcode から SVGOMG に画像をコピーする。
copyButton.addEventListener('click', async () => {
  let svg = svgOutput.innerHTML;
  showToast(i18n.t('optimizingSVG'), Infinity);
  svg = await optimizeSVG(svg);
  const textBlob = new Blob([svg], {type: 'text/plain'});
  const svgBlob = new Blob([svg], {type: 'image/svg+xml'});
  navigator.clipboard.write([
    new ClipboardItem({
      [svgBlob.type]: svgBlob,
      [textBlob.type]: textBlob,
    }),
  ]);
  showToast(i18n.t('copiedSVG'));
});

詳しくは、非同期クリップボードの記事、または次のファイルを参照してください。 src/js/clipboard.js

ファイル処理

私が気に入っている SVGcode の特長の 1 つは、それがオペレーティング システムとうまく溶け込むことです。として インストールすると、画像ファイルのファイル ハンドラやデフォルトのファイル ハンドラになります。この つまり、macOS マシンの Finder で画像を右クリックして、 SVGcode。この機能は「ファイル処理」と呼ばれ、ファイルの file_handlers プロパティに基づいて ウェブアプリ マニフェストと起動キュー。これにより、渡されたファイルをアプリが使用できるようになります。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> SVGcode アプリがインストールされている状態でデスクトップからファイルを開く。
window.launchQueue.setConsumer(async (launchParams) => {
  if (!launchParams.files.length) {
    return;
  }
  for (const handle of launchParams.files) {
    const file = await handle.getFile();
    if (file.type.startsWith('image/')) {
      const blobURL = URL.createObjectURL(file);
      inputImage.addEventListener(
        'load',
        () => {
          URL.revokeObjectURL(blobURL);
        },
        {once: true},
      );
      inputImage.src = blobURL;
      await set(FILE_HANDLE, handle);
      return;
    }
  }
});

詳細については、インストールしたウェブ アプリケーションをファイル ハンドラにするをご覧ください。また、 src/js/filehandling.js

ウェブ共有(ファイル)

OS に溶け込む別の例として、アプリの共有機能が挙げられます。仮に、 SVGcode で作成した SVG を編集したい場合、その一つの方法として、ファイルを保存することが挙げられます。 SVG 編集アプリを起動して SVG ファイルを開きますしかし、フローをスムーズにすると、 ファイルを直接共有できる Web Share API を使用する。もし SVG 編集アプリは共有ターゲットであるため、逸脱することなくファイルを直接受け取ることができます。

shareSVGButton.addEventListener('click', async () => {
  let svg = svgOutput.innerHTML;
  svg = await optimizeSVG(svg);
  const suggestedFileName =
    getSuggestedFileName(await get(FILE_HANDLE)) || 'Untitled.svg';
  const file = new File([svg], suggestedFileName, { type: 'image/svg+xml' });
  const data = {
    files: [file],
  };
  if (navigator.canShare(data)) {
    try {
      await navigator.share(data);
    } catch (err) {
      if (err.name !== 'AbortError') {
        console.error(err.name, err.message);
      }
    }
  }
});
<ph type="x-smartling-placeholder">
</ph>
SVG 画像を Gmail と共有する。

ウェブ共有ターゲット(ファイル)

その逆に、SVGcode は共有ターゲットとして機能し、他のアプリからファイルを受け取ることもできます。宛先 これを行うためにアプリは Web Share Target API。受け入れられるデータのタイプ。この処理には、 専用のフィールドを使用します。

{
  "share_target": {
    "action": "https://svgco.de/share-target/",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "files": [
        {
          "name": "image",
          "accept": ["image/jpeg", "image/png", "image/webp", "image/gif"]
        }
      ]
    }
  }
}

action ルートは実際には存在せず、Service Worker の fetch 内でのみ処理されます。 このハンドラが受け取ったファイルをアプリでの実際の処理に渡します。

self.addEventListener('fetch', (fetchEvent) => {
  if (
    fetchEvent.request.url.endsWith('/share-target/') &&
    fetchEvent.request.method === 'POST'
  ) {
    return fetchEvent.respondWith(
      (async () => {
        const formData = await fetchEvent.request.formData();
        const image = formData.get('image');
        const keys = await caches.keys();
        const mediaCache = await caches.open(
          keys.filter((key) => key.startsWith('media'))[0],
        );
        await mediaCache.put('shared-image', new Response(image));
        return Response.redirect('./?share-target', 303);
      })(),
    );
  }
});
<ph type="x-smartling-placeholder">
</ph>
SVGcode とスクリーンショットを共有する。

まとめ

SVGcode の高度なアプリ機能について簡単に説明しました。このアプリが 画像処理のニーズに不可欠なツールになります Squoosh または SVGOMG

SVGcode は svgco.de で入手できます。何をしていたのか見てみる?Google Chat では GitHub でソースコードを確認してください。Potrace は SVGcode も GPL ライセンスを取得しています。これで、ベクトル化ができるようになりました。SVGcode がお役に立てば幸いです。 その機能が次のアプリのヒントになります。

謝辞

この記事は、Joe Medley がレビューしました。