Algorithm & UI/UX
情報の欠落を「美しさ」に変える、意図的な劣化アルゴリズム
現代の写真は、レンズの進化と画像処理エンジンの向上により、あまりに「正解」を映し出しすぎます。このツールでは、あえて解像度を破壊し、色の階調を間引くことで、かつての「ガラケー画質」特有の情緒を再現しています。
このツールの入力から出力まで
現行コードの確認日:
- 入力
- 写真を選び、粗さや色の設定を調整します。
- 処理
- 縮小・再拡大や色の変換を組み合わせ、古い携帯電話の画像に見える静止画へ加工します。
- 出力
- 再描画ごとにノイズの位置が変わり、保存時にはJPEG品質0.4の圧縮も加わるため、編集画面と最終画像を比較して確認します。
まず確認する点:小さい文字は縮小時に消えます。実際の機種ごとのセンサーや保存形式を忠実に再現する処理とは分けて見ます。
仕上がりの例
写真をガラケーで撮影したような色と質感にした例です。
掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。
保存済み検証記録の条件を見る
資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。
- 記録の入力画像
- 800×1222px (JPEG)
- 記録の出力画像
- 240×366px (JPEG)
| 画面の項目 | 記録の値 | 現行コードの初期値・範囲 |
|---|---|---|
| 記録で選択されていた項目 | ノーマル | — |
| 画質の粗さ(解像度) | 240 | 初期値 240 / 範囲 120〜640 |
| 色の数(減色) | 6 | 初期値 6 / 範囲 2〜12 |
記録では「この画質で保存!」から完成表示へ進んでいます。初期値と記録値を比べてから、効果を1項目ずつ変えると作用を確認しやすくなります。
資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。
実装の確認箇所:src/pages/image/retro-phone/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。
仕組みを読み進めるときは、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)、メモリ管理と画像処理(画素バッファ、縮小と容量予算)が参考になります。
1. Canvasリサンプリングによる「ドット感」の強調
単にCSSで画像を小さく表示するだけでは、ブラウザの補間機能によって画像がぼやけてしまいます。あの頃の粗い質感を出すには、Canvas上で「補間を無効化」した状態でリサイズを行う必要があります。
具体的には、オフスクリーンCanvasを用いて一度低解像度のイメージを生成し、それを描画する際にimageSmoothingEnabled = falseを適用。これにより、ピクセルが引き伸ばされる際の滑らかなグラデーションを排除し、鋭利なドット感を維持しています。
実装の減色式を1色分にした例です。rgbは0〜255の3要素、bitDepthは画面の減色設定値です。この後に色フィルターとランダムノイズが加わります。
function quantize(rgb, bitDepth) {
const bitsPerChannel = Math.floor(bitDepth / 3) || 1;
const step = 2 ** (8 - bitsPerChannel);
return rgb.map(value => Math.floor(value / step) * step);
}
// quantize([143, 201, 89], 6) は [128, 192, 64] 2. ビット深度のシミュレーション(減色アルゴリズム)
2000年代のディスプレイは表示できる色数が限られていました。RGB各成分を一定の間隔で丸め、色の段階を減らす処理をJavaScriptで実装しています。特定機種のパレットやビット深度を厳密に再現するものではありません。
各ピクセルのRGB値を、設定値から計算した段階幅で切り下げることで、滑らかなグラデーションを「等高線」のような模様(マッハバンド)へと変化させます。これが「古いデジタル機器」特有のザラつきの正体です。
3. JPG圧縮ノイズの意図的な再現
最後の仕上げは、保存時の「圧縮ノイズ」です。当時の通信環境やストレージ容量の制限により、写真は高い圧縮率で保存されていました。
このツールでは、Canvasからデータを書き出す際、あえてクオリティ係数を低く設定することで、ブロックノイズやモスキートノイズを発生させています。これもまた、当時を感じさせる重要なスパイスとなります。
出力の仕様と確認する点
「画質の粗さ」は出力の横幅を120〜640pxで変え、高さは元の縦横比から計算します。画面で拡大されて見えても保存画像自体はこの低解像度です。大きく印刷する用途には向きません。
減色設定は内部で3分の1を整数化するので、隣り合う値で同じ階調幅になる場合があります。また、初期ラベルの「16bit」は実際の初期設定値6と一致しません。色数の厳密な指定ではなく、プレビューで質感を選ぶ設定として扱ってください。
減色の後にノーマル・セピア・モノクロ・青みを適用し、小さなランダムノイズを加えます。再描画ごとにノイズの位置が変わり、保存時にはJPEG品質0.4の圧縮も加わるため、編集画面と最終画像を比較して確認します。
大きな入力は長辺1500px以下へ縮小します。「最初からやり直す」はページ再読込で、現在の画像と設定は引き継ぎません。
