Algorithm & UI/UX
漫画の迫力をブラウザで再現する:
集中線描画とピクセル操作の裏側
写真の中央に向かって視線を強制誘導する「集中線」。単純な線描画に見えて、リアルタイムな描画パフォーマンスと、書き出し時の「漫画らしさ」を両立させるために、幾何学計算とピクセルレベルの画像処理を組み合わせています。
1. 極座標を用いた放射状ラインの高速レンダリング
数千本の線を高い密度で描画しつつ、ユーザーの操作(スライダー調整)にリアルタイムで反応させるため、本ツールでは描画の度に乱数計算を行わない「事前生成キャッシュ戦略」を採用しています。
線の角度や長さの揺らぎをあらかじめ配列に保持し、描画ループ内では Math.cos と Math.sin を用いた座標変換のみを行うことで、計算負荷を最小限に抑えています。これにより、低スペックなスマートフォンブラウザでも滑らかなプレビューを実現しました。
// 放射状ラインの座標計算ロジック
for (let i = 0; i < numLines; i++) {
const ld = cachedLines[i];
// 中心の空白領域から外側へ向かうベクトルを計算
// 独自のチューニング値を用いて自然なバラツキを表現
const innerR = baseCenterR + (maxRadius * ld.innerOffsetRatio * // 独自のチューニング値);
ctx.lineWidth = ld.lineWidth;
ctx.beginPath();
// 極座標からキャンバスのxy座標へ変換してパスを生成
ctx.moveTo(
centerX + Math.cos(ld.angle) * innerR,
centerY + Math.sin(ld.angle) * innerR
);
ctx.lineTo(
centerX + Math.cos(ld.angle) * maxRadius,
centerY + Math.sin(ld.angle) * maxRadius
);
ctx.stroke();
} 2. Canvasピクセル操作による「漫画調」フィルター
単に集中線を重ねるだけでなく、背景の写真を「漫画の1コマ」のように見せるため、独自の画像フィルタリング処理を実装しています。CSSの filter プロパティではなく、Canvasの ImageData を直接操作することで、保存(書き出し)時にフィルタ効果を完全に画像へ焼き付けることができます。
処理フローとしては、NTSC加重平均法によるグレースケール変換、輝度補正、そしてハイライトとシャドウを際立たせるコントラスト調整を1回のピクセルループ内で完結させ、実行速度を稼いでいます。
// ImageDataを用いたピクセルレベルの画像補正
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// 1. 輝度(Gray)の算出
// ここに独自の重み付けによるグレースケール計算が入ります
// 2. 明るさとコントラストの補正
// 独自の係数を用いて漫画らしいパキッとした質感を生成
let color = (/* 輝度値に対する補正計算処理 */);
// 3. 値をクランプしてRGBに再代入
data[i] = data[i + 1] = data[i + 2] = Math.min(255, Math.max(0, color));
}
ctx.putImageData(imageData, 0, 0); Developer's Note
このツールで最も苦労したのは、「迫力」の正体を数式で定義することでした。均一な線を引くだけではどこか機械的で冷たい印象になります。そこで、あえて線の太さや中心からの開始位置に「ランダムな不均一さ」を混ぜ込むことで、手描きのような躍動感を演出しています。
また、利用シーンとして「SNSへの即時投稿」を想定しているため、サーバー処理を介さない完全クライアントサイド実装にこだわりました。どんなに高解像度な写真でも、あなたの端末から一歩も外に出ることなく処理されます。
日常の何気ないラーメンの写真やペットのあくびが、このツールを通すことで「運命の瞬間」に変わる。そんな技術の遊び心を楽しんでいただければ幸いです。