このブログを閲覧していると、各記事に異なる正方形の画像があることに気づいたかもしれない。QRコードに似ているがQRコードではないキューブのパターン。記事ごとに変わる色。そして中央には常に同じ漢字:忍。

それらの画像は手動でデザインされたものではない。各記事のコンテンツ自体から生成されたものだ。

仕組み

記事を公開すると、システムは2つのデータを取得する:タイトルとコンテンツの文字数。タイトルから暗号化ハッシュ——唯一無二で再現不可能な文字列——を生成する。そのハッシュが32×32のグリッドのどのキューブを埋め、どれを空のままにするかを決定するマップになる。実際のQRコードが使うのと同じ原理だが、読み取り可能なデータはエンコードしていない。テキストのDNAを視覚的な形に変換しただけだ。

文字数が各画像のアクセントカラーを決定する:

短い記事はゴールド。中程度の長さのものはクールブルーパープルを経由する。長いものはテラコッタ。もしいつか本当に長いものを書いたら、ミントグリーンになる。

結果として、各記事がユニークな視覚的指紋を持つ。タイトルの一語を変えるだけでパターンは完全に変わる。記事が成長したり閾値を超えて縮小すると色が変異する。テキストが生きている限り、画像も生きている。

中央の漢字

各画像の中央には漢字「忍」のある白いスペースがある。日本語でしのびと読む。沈黙の中で耐え忍ぶこと、忍耐を持って持ちこたえること、見られずに動くこと。このブログの名前の由来であり、パターンがどれほど異なっていてもすべての画像を互いに結びつける視覚的な錨だ。

なぜ普通の画像を使わないのか

各記事にストックフォトやMidjourneyで生成した画像を使うこともできた。しかしこのブログはデザインとテクノロジーの交差点について語っている。画像さえもその哲学を反映してほしかった。装飾ではなくデータを形に変換したもの。読まなくても代表する記事について何かを語るもの。

実用的な理由もある。このシステムは完全に自動だ。新しい記事を公開すると、3言語すべての画像が自動生成される。写真を探す必要もPhotoshopを開く必要もどの画像を使うか考える必要もない。コンテンツが自らをイラストレートする。

技術的な詳細

このシステムはPHPとGDライブラリで動作します。外部API不要、JavaScript不要、ビルドステップ不要。記事が公開されると、画像はミリ秒で自動生成されます。 ステップ1:DNAを抽出する すべての画像は2つの入力から始まります:記事のタイトルとコンテンツの文字数です。
$charCount = mb_strlen(strip_tags($content), 'UTF-8');
$titleHash = md5($title . $postId);
$contentHash = sha1($content . $postId);
タイトルハッシュがビジュアルパターンを決定します。コンテンツハッシュがエントロピーを追加します。文字数が色を決めます。3つの入力、3つのアイデンティティの層。 ステップ2:文字数を色にマッピングする 文字数によって各記事がカラースペクトラム上に配置されます。短い記事は温かみのあるゴールド。長くなるにつれてクールブルー、パープル、テラコッタへ。9000文字を超えるとミントグリーンになります。
$colors = [
    [200, 170, 100],  // ゴールド(3000文字未満)
    [100, 170, 200],  // クールブルー(3000-5000)
    [170, 100, 200],  // パープル(5000-7000)
    [200, 120, 100],  // テラコッタ(7000-9000)
    [100, 200, 150],  // ミントグリーン(9000以上)
];

$colorIndex = min(4, intdiv($charCount, 2000));
$accent = $colors[$colorIndex];
つまり、画像を見るだけで記事の長さを推測できます。色はデータです。 ステップ3:ハッシュをグリッドに展開する MD5ハッシュ1つは32文字。グリッドは32x32=1024セル。すべてのセルをカバーするために、システムは複数のハッシュを連鎖させます:
$fullHash = $titleHash . $contentHash . md5($charCount . $postId);
$expandedHash = '';
for ($i = 0; $i < 20; $i++) {
    $expandedHash .= md5($fullHash . $i);
}
これにより640個の16進文字が生成されます。グリッドの全セルをマッピングするのに十分な量です。各16進文字(0-F、値0-15)がそのセルの運命を決めます。 ステップ4:グリッドを埋める 各セルは展開されたハッシュから1文字を読み取り、その運命を決定します:
for ($row = 0; $row < 32; $row++) {
    for ($col = 0; $col < 32; $col++) {
        $hashChar = $expandedHash[$hashIndex % strlen($expandedHash)];
        $hashVal = hexdec($hashChar); // 0-15
        $hashIndex++;

        if ($hashVal >= 10) {
            // ダークキューブ(値A-F)
            $brightness = 20 + ($hashVal - 10) * 8;
            // ほぼ黒で塗りつぶし
        } elseif ($hashVal >= 7) {
            // アクセントカラーキューブ(値7-9)
            // 文字数で決まった色で塗りつぶし
        } elseif ($hashVal >= 5) {
            // ライトグレーキューブ(値5-6)
        }
        // 値0-4:空白(白)
    }
}
分布はおおよそ:37%ダークキューブ、19%アクセントキューブ、13%グレーキューブ、31%空白。この比率により、データのように見えるほど密度がありながら、読み取れるほどの余白があるパターンが生まれます。 ステップ5:中央をクリアする グリッド中央の6x6セルの領域をクリアします。これにより視覚的な余白が生まれ、漢字ロゴのスペースが確保されます:
$centerStart = (32 / 2) - 3;
$centerEnd = (32 / 2) + 3;

for ($row = $centerStart; $row < $centerEnd; $row++) {
    for ($col = $centerStart; $col < $centerEnd; $col++) {
        imagefilledrectangle($img, $x1, $y1, $x2, $y2, $whiteBg);
    }
}
漢字「忍」(しのび――静かに耐え忍ぶこと)は、サーバー上でNoto Sans CJKフォントが利用可能な場合にレンダリングされ、同じアクセントカラーで着色されます。 ステップ6:保存して配信する 最終画像は圧縮レベル7の1200x1200 PNGです。各記事は言語ごとに1枚の画像を生成し、post-{id}-{lang}.pngとして保存されます:
$filepath = "uploads/social/post-{$postId}-{$langCode}.png";
imagepng($img, $filepath, 7);
同じ画像が3つのコンテキストで再利用されます:ホームページのサムネイル、記事内のヘッダー、そしてSNSでリンクを共有した際のOpen Graph画像。 結果 このシステムは決定論的です。同じコンテンツからは、常に同じ画像が生まれます。ランダム性なし、外部依存なし。タイトルの1単語を変えればパターン全体が変化します。段落を追加すれば色が変わる可能性があります。 最も文字通りの意味でのジェネラティブデザインです:コンテンツが自らのアイデンティティを生成するのです。 自分で実装してみよう ソースコード全体は250行未満の単一PHPファイルです。GDが有効なPHPがあれば他には何も必要ありません。コアロジック(ハッシュ展開、グリッドマッピング、色選択)はどの言語にも移植できます。原理はシンプルです:任意のユニークな文字列を取り、グリッドを埋めるのに十分なエントロピーに展開し、値の範囲をビジュアルプロパティにマッピングする。 開発者やデザイナーの方で同様のものを実装したい場合、このアプローチはAI生成やストック写真に頼ることなく、ユニークで自動的かつ決定論的なビジュアルを必要とするあらゆるコンテンツプラットフォームで機能します。