0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画像を「100KB以下」に確実に収める:品質の二分探索とリサイズの順番をブラウザで考える

0
Posted at

画像を「100KB以下」に確実に収める:品質の二分探索とリサイズの順番

社内システムや申請フォームでよくある「画像は100KB以下」という制限。ユーザーにとっては面倒ですし、作る側としても「アップロード前にクライアントで縮めてあげたい」場面は多いと思います。

この記事では、目標サイズに収める圧縮をどう組み立てるかを整理し、実際に動いている例として Nibbo の「画像を100KBに圧縮」 の挙動も紹介します。

なぜ「品質80で保存」ではダメなのか

JPEGやWebPの品質パラメータは見た目の品質を指定するもので、ファイルサイズを指定するものではありません。同じ品質80でも、青空の写真なら40KB、木の葉が写った写真なら400KBになります。サイズ上限がある場合は、品質を探索する必要があります。

基本アルゴリズム

async function encodeUnder(bitmap, maxBytes, type = 'image/jpeg') {
  let lo = 0.3, hi = 0.95, best = null;
  for (let i = 0; i < 7; i++) {
    const q = (lo + hi) / 2;
    const blob = await toBlob(bitmap, type, q);
    if (blob.size <= maxBytes) { best = blob; lo = q; } else { hi = q; }
  }
  return best; // null なら解像度を下げて再挑戦
}

function toBlob(bitmap, type, q) {
  const c = new OffscreenCanvas(bitmap.width, bitmap.height);
  c.getContext('2d').drawImage(bitmap, 0, 0);
  return c.convertToBlob({ type, quality: q });
}

ポイントは3つです。

  1. 二分探索:品質とサイズはおおむね単調なので、7回程度で十分に詰められます。
  2. 下限を設ける:品質0.3未満はブロックノイズが目立つので、そこまで下げても入らなければ品質ではなく解像度を下げます。
  3. OffscreenCanvas + Worker:メインスレッドを止めないようにWorkerで回します。

解像度を先に決めるべき理由

4000×3000(1200万画素)の写真を100KBに入れようとすると、1ピクセルあたり約0.07bitしか使えません。品質をいくら下げても破綻します。一方、1280×960にすれば約0.65bit/px。品質75前後で余裕を持って収まります。

実務では次の順番が安定します。

1. 用途から最大辺を決める(例:1280px)
2. その解像度で品質を二分探索
3. 下限品質でも入らなければ、最大辺を 0.85 倍して 2 に戻る

フォーマット選び

  • JPEG:互換性最優先。申請フォームなどはほぼこれ。
  • WebP:同画質でJPEGより25〜35%小さい。受け側が対応しているなら有力。
  • AVIF:さらに小さいがエンコードが遅く、対応していないシステムも多い。
  • PNG:写真には不向き。スクリーンショットや図版なら、色数削減で劇的に小さくなることがある。

フォーマットを変えるだけで制限を満たせることも多いので、画像変換ツールで試してみる価値はあります。

EXIFと向きの罠

  • createImageBitmap(file, { imageOrientation: 'from-image' }) を使わないと、スマホ写真が横倒しになることがあります。
  • Canvas経由で再エンコードするとEXIFは基本的に落ちます。位置情報を消したい場合は好都合ですが、撮影日時を残したい場合は別途扱いが必要です。

既存ツールを使う場合

自前で実装するまでもない、という場合はブラウザ完結型のツールが便利です。Nibbo は上記と同じ考え方で、目標サイズ(10KB〜2MBのプリセット)に向けて品質と解像度を自動調整します。処理はすべてタブ内で行われ、画像はサーバーに送信されません。ページを開いた後に機内モードにしても動作するので、業務で扱う画像でも安心して使えます。

使い方は、ページを開いて画像をドロップし、結果のサイズとプレビューを確認してダウンロードするだけです。HEICやWebPの入力にも対応しています。

まとめ

  • サイズ上限があるなら、品質は「指定」ではなく「探索」する
  • 先に解像度を決める。品質だけで頑張らない
  • フォーマット変更も有効な選択肢
  • 向きとEXIFの扱いに注意

フォームに「100KB以下」と書く側の人も、クライアント側で自動圧縮してあげるとユーザー体験がかなり良くなります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?