指でなぞると凍る画像モザイク——端末内完結のプライバシー PWA を作った

写真やスクショの一部を隠したいが、画像を Web サービスにアップロードするのは不安です。全処理がブラウザ内で完結する画像モザイク PWA「Frost」を作り、送らない・キャッシュしない・再エンコードで EXIF を落とす作りで端末内完結を担保しました。

· 1,701 字 · 9 分
目次 7 sections
  1. 01 なぜ作ったか
  2. 02 何ができるのか
  3. 03 端末の外に画像を出さない
  4. 04 使い方は「読み込んで、なぞって、保存」
  5. 05 モザイクと氷霜ガラスの 2 モード
  6. 06 インストール不要、オフラインでも動く
  7. 07 まずサンプルで試す

SNS や記事に写真・スクリーンショットを載せるとき、顔や住所、名前や番号など「ここだけは隠したい」部分が出てきます。選択肢は、手元の標準機能で黒塗りするか、Web の目隠しツールに画像をアップロードするかです。ただし後者は、隠したい画像をわざわざ外部サーバーに送ることになります。

それが気持ち悪かったので、全処理が端末内で完結する画像モザイク PWA「Frost(frost-mosaic)」 を作って公開しました。指でなぞった場所が氷霜に覆われて見えなくなる、という小さなツールです。

c12o-dev
/
frost-mosaic
Waiting for api.github.com...
00K
0K
0K
Waiting...
Frost でサンプル会員証の個人情報を氷霜で隠していくアニメーション
なぞった場所から氷霜が広がる(架空のサンプル画像)

なぜ作ったか#

出発点は、個人的な不満と「作ってみたい」が半分ずつでした。

  • 既存の Web ツールのセキュリティが気になった: 隠したい情報を含む画像を、見ず知らずの Web サービスにアップロードするのが不安だった。
  • アプリを入れるのも手間: そのためだけにネイティブアプリをインストールするのは面倒で、ブラウザだけで終わらせたい。
  • すりガラスの質感を使ってみたかった: 確実に塗りつぶすだけでなく、すりガラス(フロストガラス)のような半透明の質感で隠す表現を一度作ってみたかった。

事前に調べた範囲では、ブラウザ完結の画像 redaction(目隠し)ツールは矩形や楕円で領域を選ぶものが主流で、指でなぞるブラシ式は見当たりませんでした。だったら作ろう、というのがきっかけです。

何ができるのか#

やることは単純で、画像を読み込み、隠したい場所を指でなぞるだけです。なぞった軌跡に沿って、その下の画像が加工面に置き換わります。

加工の見せ方が「氷霜ガラス」です。なぞった所から霜が結晶化して広がり、対象を覆う見せ方です。黒塗りやモザイクのような無機質な遮蔽ではなく、冬の窓に降りる霜のような質感で隠します。隠蔽の実体はモザイクとぼかしが担い、氷霜はその上に乗るレイヤーなので、「凍らせる=隠す」という比喩と機能の向きは一致しています。見た目の演出が目的を曖昧にしないよう、比喩と機能の向きを揃えました。

実際に、架空のサンプル会員証で氏名・住所・電話番号を隠すとこうなります。

個人情報が見えている加工前のサンプル会員証
加工前:架空のサンプル会員証
氷霜で個人情報を隠したサンプル会員証
加工後:氏名・住所・電話番号を氷霜で覆った状態

端末の外に画像を出さない#

このツールの核は「画像が端末の外に出ない」ことです。主張だけでなく、実装の構造でそうなるようにしています。

  • 送らない: 読み込みは FileReader で行い、加工は Canvas 2D 上で完結します。画像をサーバーへ送信する処理を持たない作りです。
  • EXIF / GPS が落ちる: 保存は canvas.toBlob('image/png') で再エンコードします。そのため元画像に含まれていた撮影日時や位置情報などのメタデータは出力に残りません。
  • キャッシュしない: オフライン動作のために Service Worker でアプリ本体(HTML・JS・CSS など)はキャッシュします。ただし ユーザーが読み込んだ画像はキャッシュ対象に含めていません。

「ローカルで処理します」と書くだけなら簡単です。送らない・キャッシュしない・再エンコードで EXIF を落とす、という動作を実装に織り込んで主張を裏打ちしています。この設計の詳細は別記事で掘り下げる予定です。

使い方は「読み込んで、なぞって、保存」#

操作の流れはこれだけです。

  1. 画像を読み込む(ファイル選択、または空状態の枠をタップ)
  2. 隠したい場所を指でなぞる
  3. 必要ならスライダーで調整する
  4. 保存する

調整できるのは 4 つのスライダーです。

スライダー範囲役割
粗さ6–48pxモザイクのブロックの大きさ
ぼかし0–14px加工面のぼかし量
氷霜0–100%霜レイヤーの濃さ
ブラシ10–90pxなぞる円の太さ

直近のストロークの取消と全消去もできます。長い縦長スクショなどは、2 本指でズーム・パンして拡大すれば細部も塗れます(1 本指は描画、2 本指がズーム・パンです)。

保存すると <元画像名>_<モード>.png(例: IMG_1234_frost.png)という名前の PNG が得られます。iOS では共有シート経由、Android やデスクトップでは直接ダウンロードと、環境に合わせて保存方法を出し分けています。

モザイクと氷霜ガラスの 2 モード#

隠し方は 2 モードあります。

  • モザイク: 縮小→拡大によるブロック化。昔ながらの素直なモザイクです。
  • 氷霜ガラス: モザイクを下地に、ぼかしとガラス質感、霜レイヤーを重ねたモード。

同じ会員証を、それぞれのモードで隠すと印象が変わります。

モザイクモードで会員証を隠した編集画面
モザイクモード:ブロック状に粗くする
氷霜ガラスモードで会員証を隠した編集画面
氷霜ガラスモード:霜の質感で覆う

氷霜スライダーを 0 にすると霜レイヤーは消え、モザイク+ぼかしだけが残ります。きっちり隠したい場面と、雰囲気を保ったまま隠したい場面で使い分けられます。

インストール不要、オフラインでも動く#

Frost は PWA(プログレッシブ Web アプリ)です。ブラウザで開けばそのまま使えますし、ホーム画面に追加すればアプリのように起動し、2 回目以降はオフラインでも動きます。アプリ本体はランタイム依存ライブラリゼロの素の TypeScript で書いていて、ツール本体のバンドルは gzip で約 5KB と軽量です。

まずサンプルで試す#

自分の画像を選ばなくても、frost.c12o.net/app?sample=1 を開くと同梱のサンプル画像が端末内で読み込まれ、なぞる・調整する・保存するの一連をそのまま試せます。

ソースは MIT ライセンスで公開しています。実装の詳しい話はそれぞれ別記事にまとめていきます。Canvas を 4 枚合成してマスク描画する仕組み、保存の方法を iOS と Android / デスクトップで出し分けた話、ズーム時に座標がずれない工夫などです。

記事一覧