プレビューは完璧に見えました。6000px のポスター全面にヴィンテージ調のフィルターをかけ、輪郭もグラデーションも滑らか。ところが書き出した PNG を等倍で開くと、画像に沿って薄い縦の継ぎ目が走っていました。ほんのわずかに色調がずれた帯です。プレビューには一度も出ていませんでした。この「見た目」と「成果物」のずれは、バグというより、ブラウザで画像処理を完結させる以上は避けて通れない構造の話だと考えています。
ブラウザ上のキャンバス編集は、デスクトップアプリがあまり意識しない制約に直面します。メモリです。Online Design(imging.ai)は片辺 8192px、およそ 4800 万画素、最大 24 レイヤーまで扱え、しかも処理はすべて端末内で完結しアップロードは行いません。とはいえスライダーを動かすたびに全レイヤーを原寸で保持すればタブは固まります。ですから操作するプレビューは、キャンバス原寸ではなくビューポートに合わせて縮小した解像度で描かれています。
フィルター(12 種のプリセットと 18 項目の微調整)は、その縮小バッファに対して走ります。速く、しかも正しく見える。画面サイズでは原寸版と視覚的に区別がつかないからです。ところが書き出しの瞬間、ツールはプレビューを破棄し、元のキャンバス原寸でフィルターを合成し直します。画素グリッドが違えば結果も変わり、原寸でしか現れない要素が姿を出す余地が生まれます。
継ぎ目の正体はここにあります。原寸では 4800 万画素のフィルター 1 パスがブラウザの一括確保の上限を超えることがあるため、高解像度のフィルター処理は帯状(ストリップ)に分割して行われます。各帯を完全に孤立させて処理すると、近傍画素を参照するフィルター(ぼかしやシャープなどカーネルを持つもの)は帯の端で参照先を持たず、切れ目の両側がわずかに異なる近傍から計算され、これが継ぎ目になります。
対策は各帯に「のりしろ」を持たせることです。帯を共有辺の側に少し広げ、その余白を含めて処理し、カーネルが常に実在の近傍を参照できるようにしてから、余白を切り落として帯を貼り合わせます。両側が同じ周辺情報で計算されるため継ぎ目は消えます。プレビューは 1 バッファに収まるのでこの処理が不要で、だからこそ書き出し時にだけ症状が出たわけです。
自分で確かめるなら手順は短いです。書き出したい原寸でキャンバスを作成し、画像をレイヤーとして読み込み、単一レイヤーまたはキャンバス全体にフィルターを適用し、PNG か WebP で書き出して、結果を等倍と 400% で開きます。プレビューは代理であって、書き出したファイルこそが真実です。両者が食い違うなら、それは色の問題ではなく解像度と分割の問題だと切り分けられます。
切り分けが楽だったのは、編集が非破壊だからです。フィルターはパラメータとして保存され、元画像は再エンコードされず、.imging ファイルに保存して開き直せます。同じフィルターを何度も上下させて書き出しを比べても、元画像は劣化しません。おかげでストリップ処理の挙動を特定するのは一日仕事ではなく数分で済みました。
得た教訓は地味ですが確実です。ブラウザの画像ツールは、プレビューではなく原寸・最大ズームでの書き出しで判断すること。プレビューは速く、画面サイズで正しく見えるよう最適化されています。原寸でしか現れないもの——バンディング、継ぎ目、甘さ——は、その二つの隙間に棲んでいて、そここそが本当の作り込みどころです。
