画像と写真 · Social Image Resizer
ブラウザー画像のサイズ変更の仕組み: Canvas、drawImage、およびリサンプリング
· 仕組み
画像のサイズ変更 キャンバス ブラウザ処理
ブラウザーは、写真をデコードし、新しいサイズでキャンバスに描画し、結果をエンコードできます。すべてサーバーなしで実行できます。この投稿では、そのパイプラインに従い、品質の勝敗がどこで決まるのかを説明し、サイズ制限がデバイスのメモリだけである理由を示します。
アップロードなし、サーバーなし、サイズ変更済み — ページが 20 メガピクセルの写真を縮小するときにどこで作業が行われるかという具体的な問題
写真は、画像処理サーバーにアクセスせずに、1080 または 1350 のポートレートにすることができます。 Social Image Resizer はブラウザー ピッカーからファイルを受け取り、その MIME タイプとサイズを検証し、createImageBitmap を呼び出します。デコードされたビットマップは選択されたすべての出力のソースとして残るため、1 つのローカル オブジェクトが複数の異なる形状のキャンバスにフィードすることができます。
表示されるプレビューは、ネットワーク要求の背後に隠された最終的なエクスポートではありません。これは、同じフレーミング状態 (ターゲット比率、ズーム、オフセット、フィット モード、背景) の小さいキャンバス レンダリングです。後でエクスポートすると、事前設定された寸法でレンダリングが繰り返され、Blob がエンコードされ、Blob がページ内のダウンロード コントロールに渡されます。
デコードはローカルですが、このツールは 40 MB 入力制限も強制します
計画では、デバイス メモリが唯一の実際的な境界であると述べていますが、出荷された入力パスには明示的な 40 MB ファイル制限もあります。 JPEG、PNG、および WebP は受け入れられます。他のタイプはデコード前に拒否されます。そのゲートの後、createImageBitmap はブラウザーに、圧縮ファイルのバイトをキャンバスで使用可能な幅、高さ、およびデコードされたピクセルに変換するように要求します。
デコードされたピクセルは圧縮ファイルよりも多くのメモリを占有する可能性があり、各出力キャンバスには独自の割り当てが必要です。したがって、レンダラーは、キャンバスを作成する前に共有ピクセルバジェット ガードを呼び出します。これは 2 番目のデバイス指向の制約であり、40 MB 以下のすべてのファイルがすべてのマシンで要求されたすべての出力に適合することを約束する権限ではありません。
出力キャンバス クリップがオーバーフローしている間、drawImage は位置決めされた完全なビットマップをスケールします。
ToolAcre はソース クロップ四角形を計算せず、8 つのソースと宛先の引数をdrawImage に渡します。ソースとターゲットの寸法からスケールを計算し、スケールされたビットマップ全体を配置して、エッジがオーバーフローをクリップするキャンバス上に描画します。カバー モードでは、クリッピングがクロップになります。包含モードでは、ビットマップ全体が表示されたままになります。
トリミングとサイズ変更は同義語ではないため、区別は重要です。サイズを変更すると、ビットマップがサンプリングされる次元が変わります。トリミングにより、有限の出力フレームの外側にあるものはすべて削除されます。ここでは 1 つのdrawImage 呼び出しが両方の効果に参加できますが、クロップは最初にソース ファイルを書き直すのではなく、フレーム ジオメトリとクリッピングによって生成されます。
内部でのリサンプリング — スムージング設定、「高品質」ヒントがブラウザーに要求する内容、およびブラウザー間で結果がわずかに異なる理由
描画前に、レンダラーは imageSmoothingEnabled を有効にし、imageSmoothingQuality を高に設定します。これらはブラウザーのキャンバス コントロールであり、名前付きの Lanczos、bicubic、またはその他のカーネルに対するリクエストではありません。 API はブラウザの正確な係数テーブルではなく品質のヒントを公開するため、実装ではエンジン間で同一のサンプルを保証することはできません。
有用な比較では、ソース、出力寸法、ブラウザを固定したまま、斜めのエッジ、細い線、繰り返されるテクスチャを検査します。別のブラウザがわずかに異なっていても、それはターゲット比率が変更されたことを意味するものではありません。これは、同じジオメトリック リクエストが別のキャンバス実装を介して渡されたことを意味します。これが、まさにこの記事がパフォーマンスや品質のパーセンテージをでっち上げないようにしている理由です。
出力をエンコードする — キャンバスをエンコードされた画像ファイルに戻し、ダウンロードできるようにする
エクスポート キャンバスは、このメソッドが存在する場合は OffscreenCanvas.convertToBlob を通じて Blob になり、それ以外の場合は HTMLCanvasElement.toBlob になります。ユーザーは JPEG、PNG、または WebP を選択します。品質値はエンコーダーに提供されますが、PNG は JPEG や WebP のような非可逆品質制御を使用しません。結果のバイト数は推定ではなく測定されます。
選択されたいくつかのターゲットについて、ツールは各 BLOB を順番に構築し、実際の寸法と測定されたサイズを表示し、すでにエンコードされたファイルを ZIP にパッケージ化できます。ここでは、ZIP ストレージによって画像圧縮が向上するわけではありません。コンテンツには、これらの形式がすでに圧縮されていることが記載されています。個々のダウンロードとアーカイブはどちらもローカルで作成されたバイトから始まります。
この実装は、Web ワーカーではなくメインスレッドでエクスポート作業を実行します。
ワークブックでは、負荷の高い作業は通常 Web ワーカーで実行されると述べていますが、このアプリはクロップ関数とレンダリング関数を main.js に直接インポートし、そこでターゲットをループします。検査されたパスにはワーカーは作成されません。ページは引き続き通常のジョブに使用できますが、存在しないアーキテクチャのせいではなく、応答性を観察する必要があります。
ネットワーク分離は 2 種類の証拠によってサポートされています。コア テストではネットワーク ガードをインストールし、すべてのプリセットを試行なしでフレーム化しますが、製品レコードでは処理がローカルであることがマークされます。実行時のネットワーク パネル チェックにより、展開の証拠を追加できます。ページ全体がリクエストを行わないと主張するのではなく、画像のアップロードを通常のページアセットや開示された分析から区別する必要があります。
これでカバーされないもの — GPU アクセラレーションによるサイズ変更ライブラリとサーバー側の画像パイプライン
このルートは、GPU ライブラリやリモート メディア パイプラインではなく、ブラウザー プリミティブに基づいて意図的に構築されています。選択可能なリサンプリング カーネルや代替アルゴリズムのベンチマークを公開したり、バッチ処理の高速化を約束したりするものではありません。 1 つのソース画像から複数のクロップが生成されます。無関係なソース ファイルの多くは別のワークフローに属しています。
これらの除外により、Promise のテストが可能になります。このコードは、ファイルの検証、ビットマップのデコード、算術フレーム化、キャンバス描画、Blob エンコード、およびダウンロード アセンブリを証明します。サーバー ファームが同じピクセルのサイズをどのように変更するか、ブラウザが内部でどの GPU パスを選択するかについては証明されていません。クレームは、使用される監視可能な Web API で停止します。
要点: ブラウザーにはすでにリサイザーが組み込まれています。Social Image Resizer がそれを実行し、ファイルをアップロードせずにプラットフォームのアスペクト比に合わせてトリミングおよびスケーリングします。
ブラウザーはすでに重要な操作を提供していますが、有用な結果はその周囲の正しいジオメトリに依存します。 Social Image Resizer は、カバーの最大スケール、包含の最小スケールを選択し、動きをクランプし、安全領域ガイドを個別にプレビューし、正確なターゲット寸法でエクスポートします。このオーケストレーションにより、低レベルの描画 API が反復可能なソーシャル アセット ワークフローに変わります。
以前に縮小したコピーではなく、元のイメージを使用してパイプラインをテストします。現在のツール プリセットまたはカスタム比率を選択し、被写体を移動し、一度エクスポートして、ダウンロードした寸法を検査します。証拠は、受信したローカル ファイルとそれを作成したコード パスであり、すべてのブラウザが同一の隠しリサンプラーを使用しているという主張ではありません。