ai-lab.org
ASCIIBake

ASCIIBake ができるまで — Canvas だけで画像を文字に焼く軽量ピース

Canvas API の createImageBitmap → drawImage → getImageData だけで画像の明暗を読み、 文字ランプにマップする アスキーアート生成ツールの設計記録。 ML / WASM / モデル不要、 純 JS で 12本目を埋めた話。

·decision改善·stage公開中

ASCIIBake ができるまで — Canvas だけで画像を文字に焼く

ASCIIBake は、画像をブラウザ内で アスキーアート (ASCII art)に変換する Webサービスです。 ML も WASM も外部 API も使わず、 Canvas API の createImageBitmap → drawImage → getImageData だけで完結。 メディア処理ラボ 11本柱に続く 12本目、 新カテゴリ 「クリエイティブ / 視覚遊び」 を追加しました。

なぜこの形にしたか

ラボはここまで 「重いライブラリをブラウザで動かす」 ことを示すサービスを中心に出してきました。 voice-scribe / word-warp / bg-snap などはモデル DL に数十〜数百MB かかる。

逆に モデルゼロ・WASM ゼロ・依存ゼロ の軽量ピースがあると、 「ブラウザ完結」 の幅が広がります。 アスキーアート (ASCII art)化は明暗を文字に置き換えるだけの古典タスクで、 Canvas API でそのまま書ける。 「重い処理だけがブラウザ完結の価値ではない」 を 12本目で示す位置づけです。

visual direction

フォスファーグリーン × CRT ブラック (vintage terminal)。

  • 真黒の背景 (#000000)
  • フォスファーグリーン (#39ff14) を主色、 text-shadow で残光
  • アンバー CRT 残光 (#ffb000) を副色
  • 横方向の CRT スキャンライン (背景パターン)

既存 11本 (mint / amber / violet / cobalt / lime / gold / rose / indigo / emerald / vermilion / uranium) と完全に別軸で、 アスキーアート (ASCII art)の 「ターミナル時代」 メタファーを濃く出しました。

実装の見どころ

1. Canvas で 1工程完結

const bitmap = await createImageBitmap(file)
const canvas = document.createElement("canvas")
canvas.width = cols
canvas.height = rows
const ctx = canvas.getContext("2d")
ctx.drawImage(bitmap, 0, 0, cols, rows)
const data = ctx.getImageData(0, 0, cols, rows).data

ファイルを読む → 縮小して描画 → ピクセルデータ取得。 これで終わり。 ライブラリ 0、 モデル 0、 ネットワーク 0。

2. 文字セルのアスペクト補正

モノスペースフォントは概ね 2:1 (縦長) の比率です。 cols だけ指定して rows をピクセル比でそのまま割ると、 出力 ASCII が縦に潰れて見えます。 cellAspect (charset ごと) を導入して:

const rows = Math.round((cols * srcAspect) / charset.cellAspect)

charset によって最適セル比は変わります — ブロック文字 (█▓▒░) は 1:1 で、 標準ランプ (@%#*+=-:.) は 2:1。 これを charset ごとにメタとして持たせて自動補正。

3. 輝度計算 + アルファ合成

Rec.601 で R/G/B から輝度を計算。 透過部分は白に合成 (PNG の透過は白背景と仮定):

const yLum = (0.299 * r + 0.587 * g + 0.114 * b) / 255
const aN = a / 255
const lum = yLum * aN + (1 - aN) * 1

これで透過 PNG (アイコン等) も意図通り焼ける。

4. 文字セット 4種

  • 標準: @%#*+=-:. (10階調) — ディテール重視、 写真向き
  • ブロック: █▓▒░ (5階調) — ピクセルアート風、 一見で形が伝わる
  • ミニマル: #+-. (5階調) — 印刷向き、 紙でも読める
  • 二値: # (2階調) — SVG / 簡素ロゴ向き

charset を変えるたびに即座に再ベイク (useEffect で file / charset / cols / invert を監視)。

5. §8.5.2 invariants

return {
  text: lines.join("\n"),
  cols, rows, charset,
  charsUsed: Array.from(charsUsedSet).sort(),
  srcWidth, srcHeight,
  inferMs,
}

charsUsed は出力に実際に登場した文字の重複排除リスト。 e2e で 「charsUsed が charset の ramp の strict subset である」 を assert して silent ramp drop を防ぎます。 result panel の data attribute (data-cols / data-rows / data-chars-used) で直接読める。

このサービスから言える事

ラボの 12本柱:

  • voice-scribe / clip-cast / bg-snap / text-pluck / pdf-anvil / pixel-lift / pic-flip / mind-cell / beam-drop / word-warp / exif-peel / ascii-bake

カテゴリ:

  • 認識 (voice / text / bg)
  • 変換 (clip / pdf / pixel / pic / word)
  • 生成 (mind)
  • 転送 (beam)
  • インスペクション (exif)
  • クリエイティブ / 視覚遊び (ascii) ← 新

「ブラウザ完結 = 重いライブラリだけ」 ではなく、 軽量ピースもラボの幅を広げる。 12本目はその実証として置きました。

[ ./next_action ]

読んだら、 ASCIIBake を実際に動かす。

この開発ログは ASCIIBake をどう作ったかの記録です。 読み終わったらそのままサービス本体へ戻って、 実物で価値を確かめてください。

[ ./related_logs ]

関連する開発ログ

all logs →
PyPad

PyPad ができるまで — Pyodide でブラウザ完結の Python REPL を作る

Pyodide (CPython を WebAssembly にコンパイルしたランタイム) を CDN side-load して、 入力したコードがブラウザの外に出ない Python REPL を構築した設計記録。

read log →
ExifPeel

ExifPeel ができるまで — ブラウザだけで画像のEXIFを確認・剥離する設計

exifr (EXIF パーサ) と piexifjs (JPEG EXIF 操作) と Canvas API をブラウザ内で動かし、 GPS / 撮影機種 / 編集ソフト履歴を覗いて剥がすツールの設計記録。 JPEG ロスレス strip と PNG/WebP の Canvas 再エンコード戦略、 GPS 警告 UI まで解説します。

read log →
WordWarp

WordWarp ができるまで — OPUS-MT をブラウザで動かして翻訳をローカル化する

@xenova/transformers と OPUS-MT (Helsinki-NLP) の量子化版で、 テキストをサーバーに送らずブラウザ内推論で翻訳する Webサービスの設計記録。 言語ペア切替、 段落分割、 IndexedDB キャッシュ、 8ペア対応の UX まで解説します。

read log →
BeamDrop

BeamDrop ができるまで — trystero + WebRTC でファイルをサーバー経由せずに直送する

trystero (Nostr 公開リレー) と WebRTC DataChannel で、 ファイル本体をサーバー経由せずブラウザ間で直送する P2P 共有ツールの設計記録。 signaling とペイロードの分離、 QRコード / 部屋コードの UX、 NAT越えとリレーの安定性まで解説します。

read log →
MindCell

MindCell ができるまで — ブラウザだけで LLM を動かすチャット設計

@mlc-ai/web-llm を WebGPU 上で動かして、 ローカル推論の AI チャットをブラウザ完結で実装した Webサービスの設計記録。 ストリーミング応答、モデルロード進捗、対応外環境の扱いまで解説します。

read log →
PicFlip

PicFlip ができるまで — ブラウザ内 libheif + Canvas で画像形式変換を成立させる設計

heic2any (libheif WASM) と Canvas API で HEIC / JPG / PNG / WebP のクロス変換をブラウザ完結で実装したWebサービスの設計記録。バッチ・品質スライダー・暗室セーフライト演出までを解説します。

read log →