猫の手ツール

Image Processing & Typography

ピクセル輝度解析と縦書きCanvas描画の裏側

「匿名インタビュー画像」を作るために必要なのは、単に画像を暗くすることではありません。背景の光を残しつつ人物を潰す「逆光感」と、ドキュメンタリー番組特有の「縦書き字幕」をブラウザだけで再現するためのアプローチを解説します。

1. Luma(輝度)ベースの動的シルエット・フィルタ

画像をシルエット化する際、全ピクセルの明るさを一律に下げるだけでは、のっぺりとした不自然な画像になってしまいます。本ツールでは、各ピクセルのRGB値から人間が感じる明るさ「Luma」を算出し、特定のしきい値を境に階調を圧縮する処理を行っています。

メリット: 背景の明るい部分は比較的残しつつ、人物の顔など「影になっている部分」を重点的に潰すことで、テレビ番組の逆光演出のようなミステリアスな質感をシミュレートできます。

// ピクセル単位の輝度解析ロジック
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
    const r = data[i], g = data[i+1], b = data[i+2];
    
    // 人間の視覚特性に基づいた輝度算出(Luma)
    // 0.299R + 0.587G + 0.114B
    const luma = // 独自の輝度計算式;

    if (luma < threshold) {
        // 暗い部分はさらに深く潰す
        data[i] *= // 独自の減衰係数;
    } else {
        // 明るい部分も階調を落として「逆光」を演出
        data[i] *= // 独自の減衰係数;
    }
    
    // カラーフィルター(寒色・暖色など)の動的合成
    // ...
}

2. 1文字ずつの座標変換による「Canvas縦書き」実装

HTML5 Canvasには、標準でテキストを縦書きにする機能が存在しません。本ツールでは、文字列を1文字ずつ分割し、Canvasの座標系を文字サイズに合わせて移動させながら垂直方向にレンダリングしていく独自のレイアウトエンジンを実装しています。

メリット: ブラウザの制約を超えて、日本語ドキュメンタリー特有の「語りの字幕」を自由な位置に配置できます。また、長音符「ー」や括弧、句読点などの記号は、90度回転させて位置を微調整する処理を加えることで、自然な縦書きを実現しています。

// 文字列を垂直に並べるレイアウト処理
function drawVerticalText(ctx, text, startX, startY, fontSize) {
    const chars = text.split('');
    let currentY = startY;

    chars.forEach(char => {
        ctx.save();
        ctx.translate(startX, currentY);

        // 記号(ー、。、など)を判定して回転
        if (isSpecialChar(char)) {
            ctx.rotate(Math.PI / 2);
            ctx.translate(0, -fontSize * // 独自の補正値);
        }

        ctx.fillText(char, 0, 0);
        ctx.restore();
        
        // 次の文字へ座標を移動
        currentY += fontSize * // 独自の行間係数;
    });
}

3. クライアントサイドでの画像リサイズ・ガードレール

最近のスマートフォンの写真は極めて高解像度であり、そのままCanvasでピクセル操作を行うとメモリ不足でブラウザがクラッシュするリスクがあります。本ツールでは、読み込み時にアスペクト比を維持したまま、処理に最適な最大解像度へ動的にリサイズしています。

メリット: 処理の高速化だけでなく、出力されるJPEGファイルのサイズをSNS等への投稿に最適な数MB程度に自動調整する役割も兼ねています。

// 過大な画像を安全なサイズにリサイズ
const MAX_DIMENSION = // 独自の制限値;
let targetWidth = img.width;
let targetHeight = img.height;

if (targetWidth > MAX_DIMENSION || targetHeight > MAX_DIMENSION) {
    const scale = MAX_DIMENSION / Math.max(targetWidth, targetHeight);
    targetWidth = Math.floor(targetWidth * scale);
    targetHeight = Math.floor(targetHeight * scale);
    
    // このサイズでオフスクリーンCanvasを作成し、描画を開始
    // ...
}

Developer's Note

このツールの開発において最も時間をかけたのは、実は「走査線(TVノイズ)」の間隔と濃さの調整です。4ピクセルおきに1ライン、透明度20%程度の黒線を引くという極めて単純な処理ですが、これがあるだけで一気に「ブラウン管感」が出て、脳内で勝手にあの低い変調ボイスが再生されるようになります。

また、縦書きの字幕機能を実装したのは、単に「面白いから」だけではありません。顔をシルエットで隠すという行為は、心理的に「内密な話をしている」という文脈を強化します。そこに縦書きの字幕が加わることで、静止画でありながらストーリーを感じさせる演出が可能になりました。

サーバーに一切データを送らず、あなたのプライベートな写真をあなたの端末だけでおもしろ画像に変える。そんな「安全な遊び場」をフロントエンド技術だけで構築することにこだわりました。