3 ポイント 投稿者 GN⁺ 2024-06-08 | 1件のコメント | WhatsAppで共有
  • ASCII Silhouettifyは、ロゴ・バナー・ピクセルアートのようなフラットで高コントラストなグラフィックを、95個の表示可能なASCII文字だけで埋めたシルエットASCIIアートに変換するブラウザ・コマンドラインアプリ
  • 入力として png, svg, jpg, webp, gif, tif, heif, avif, pdf を受け付けるが、陰影・ハイライト・影・グラデーションはレンダリングしないため、写真の変換には不向き
  • 出力はANSIカラーテキスト、プレーンテキスト、HTML、NeofetchカスタムASCIIアート形式をサポートし、Neofetch形式は256色拡張ANSIパレットのうち6色に制限される
  • 変換アルゴリズムは画像を色平面に分割した後、各9×19ピクセル領域でシルエットの輪郭を侵さないASCII文字の中から最も大きい文字を選ぶ
  • 性能向上のために95ビットアキュムレータ、171個のビットマスク、leading zeros計算、論理プロセッサ並列処理を用い、パレットマッチングには計算コストの高いCIEDE2000知覚色差式を適用する

ASCIIシルエット変換アプリ

  • ASCII Silhouettifyは画像をASCIIシルエットに変換するアプリ
    • ASCIIシルエットは、線や質感よりも均一に塗りつぶされた幾何学的な形状が際立つASCIIアートのスタイル
    • ロゴ、バナー、ピクセルアートのような、ミニマルで高コントラストかつ立体的な奥行きのないフラットグラフィックに向いている
    • 陰影、ハイライト、影、グラデーションをレンダリングしないため、写真には向いていない
  • 文字セットは、伝統的なASCIIアーティストの媒体である95個の表示可能なASCII文字に制限される
    • ANSIアートで一般的な線・ブロック文字や、kaomojiで使われる多くのUnicode文字は使用しない
  • 出力形式は設定によって異なる
    • 単色のプレーンテキスト
    • ANSIエスケープシーケンスで色付けされたテキスト
    • 色ありまたは色なしのHTML
    • Neofetch ASCIIアート形式
  • ブラウザとコマンドラインで利用できるデスクトップアプリ

UbuntuロゴとNeofetchの例

  • 例では、Ubuntuインスタンス上の Neofetch 出力にASCII Silhouettifyの結果を組み込む流れを示している
  • 最適なASCIIアートを得るために、Webから高解像度のUbuntuロゴ画像を取得し、まずコンソールで表示されるサイズにスケーリングする
  • コマンドライン版で画像を変換すると、デフォルトでANSIエスケープシーケンス付きのカラーテキストが生成される
  • -o フラグで、Neofetchが表示するファイルに出力を送れる
  • NeofetchはANSIアートとOS指標の間に広い余白を入れるため、例では NeofetchカスタムASCIIアートファイル形式 を使用している
    • 出力ファイルの1行目は色インデックスの一覧
    • 以降の行はエンコードされた画像
    • テキストエディタで1行目をクリップボードにコピーしてから削除する
    • Neofetch実行時に、クリップボードに保存した値を貼り付けて使う
    • 恒久的に適用するには、Neofetchのbashスクリプトの一部を同じ値に置き換える
  • 元のロゴを生成結果の上に重ねて比較すると、アルゴリズムが各色領域の輪郭内に収まる最も大きい文字を選ぶ方式が分かる

インストールと削除

  • コマンドライン版はNode.jsアプリケーション
  • Node.jsがない場合は、先にNode.jsのインストール手順を行う必要がある
  • macOSとLinuxでは、rootユーザーなしでグローバルインストールできるよう npm の設定が必要
  • インストールコマンド:
    • npm install -g ascii-silhouettify
  • 削除コマンド:
    • npm uninstall -g ascii-silhouettify

入力・出力オプション

  • ブラウザ版とコマンドライン版は同じオプションセットをサポートする
    • コマンドライン版の -h フラグはオプション要約メッセージを出力する
  • 複数の画像を一度に変換できる
    • 対応形式は png, svg, jpg, webp, gif, tif, heif, avif, pdf
    • コマンドライン版の -i フラグは複数のファイル名パターンマッチ規則を受け取る
    • 入力画像は黒または透明な背景である必要がある
  • 出力は4つの系統に分かれる
    • プレーンテキストまたはANSIカラーテキスト
    • HTML形式の等幅テキスト
    • NeofetchカスタムASCIIアート形式
    • Neofetch形式は256色拡張ANSIパレットのうち6色に制限される
  • パレットのデフォルト値は、256色拡張ANSIパレットから標準16色ANSIパレットを除いた240色
    • 標準ANSIパレット16色は、現代のターミナルエミュレータで再定義されることが多いため、デフォルトから除外されている
    • ユーザーは、標準ANSIパレットの先頭8色、標準ANSI16色全体、拡張ANSI256色全体、デフォルトの240色パレットを選択できる
  • 出力に現れる最大色数を指定できる
    • 黒背景と見なされる色はカウントしない
    • デフォルト値は255
    • 単色モードでは実質的にこの値は1に設定される
    • NeofetchカスタムASCIIアート形式のデフォルト値は、その形式の最大値である6

表示サイズと変換品質の調整

  • ターミナルエミュレータで生成されたASCIIアートの縦横比は、フォント、フォントサイズ、行の高さ、文字サイズの丸め規則によって変わる
  • 最適化のために、ターミナルのテキスト画像をキャプチャし、行間の空白を含む各等幅文字のピクセルサイズを測定する
  • 開発者のWindowsデスクトップ基準の測定例は次の通り
    • IntelliJ Terminal: 文字 8×22、フォントサイズ 10、行の高さ 1.65
    • Putty: 文字 8×16、フォントサイズ 10、行の高さ 1.2
    • Notepad: 文字 10×18、フォントサイズ 13、行の高さ 1.04
    • Notepad++: 文字 9×19、フォントサイズ 12、行の高さ 1.2
    • Windows Command Prompt: 文字 8×16、フォントサイズ 10、行の高さ 1.2
    • Windows Console Host: 文字 9×20、フォントサイズ 12、行の高さ 1.25
    • Windows Terminal: 文字 9×19、フォントサイズ 12、行の高さ 1.2
  • 入力画像は、ターミナルに表示したいサイズへペイントソフトで事前にスケーリングしておくのが理想的
    • 細かな調整のために、ASCII Silhouettifyは画像スケーリング係数を受け取れる
    • デフォルト値は1
  • 変換アルゴリズムは、明度5%未満の領域を空白文字に置き換えて黒い背景を完全に見せる
    • ユーザーはこの暗さのしきい値を調整できる
  • デフォルトでは利用可能なすべての論理プロセッサに作業を分散する
    • ユーザーは割り当てるプロセッサ数を1個まで減らせる
    • プロセッサ数を減らすと処理時間は長くなる

変換アルゴリズム

  • 開発者がASCII Silhouettifyを作成したWindowsデスクトップでは、Terminalはデフォルトの12ポイント・1.2em Cascadia Mono設定時に、各等幅文字を9×19ピクセルの矩形内にレンダリングする
  • アルゴリズムは95個の表示可能なASCII文字の画像をキャプチャし、50%強度基準でしきい値処理して白黒ピクセルだけを持つ文字画像を作る
  • ソース画像は固有の色平面に分離される
    • 各平面は黒背景上の白いシルエット
  • 各色平面は9×19ピクセルの矩形領域の行列に分割される
    • 各領域は1つのASCII文字に置き換えられる
  • 最適な文字は、領域とすべてのASCII文字画像をピクセル単位で比較して選ばれる
    • 文字画像の白ピクセルが領域の黒ピクセルと重なる場合、シルエットの輪郭を歪めないよう、その文字は除外される
    • 残った文字の中から、白ピクセル一致数が最も多い文字を選ぶ
  • 領域を文字に置き換える際、一致した白ピクセル数を記録する
    • すべての平面を変換した後、最も高い一致白ピクセル数を持つ文字を選んで平面を結合する
    • 最終文字は、その文字が由来した平面の色で塗られる

ビットマスクベースの高速化

  • 変換前にASCII文字画像を白ピクセル数基準でソートする
    • 空白文字は白ピクセル数が0で最少
    • @ 文字は白ピクセル数が最多
  • アルゴリズムは @ から下へ向かって各領域と文字画像を比較する
    • シルエット内に完全に収まる文字が見つかった時点で、その領域をその文字に置き換える
    • ソートにより、その文字が白ピクセル数最大の候補になる
  • 速度を大幅に上げるため、9×19領域の各ピクセルに対して171個のビットマスクを用意する
    • 各ビットマスクは、その座標に黒ピクセルを持つASCII文字画像の集合を表す
    • 各ビットマスクは95ビットを含む
    • bit-0は空白文字、bit-94は @ 文字に対応する
  • 領域変換中は、95ビットアキュムレータで使用可能なASCII文字候補集合を徐々に絞り込む
    • 開始時、アキュムレータは全ビット1で初期化される
    • 領域の各黒ピクセルについて、現在のアキュムレータと対応するピクセルのビットマスクをbitwise ANDする
    • この演算により、領域の黒ピクセル位置に白ピクセルを持つ文字画像を除外する
  • 領域全体の処理後、アキュムレータのset bitが置換可能な文字候補になる
    • 文字はソート済みなので、アキュムレータのleading zeros数が、シルエット内に完全に含まれる白ピクセル数最大のASCII文字画像のインデックスになる
    • ライブラリの助けを借りて、マイクロプロセッサのleading zeros計算命令を呼び出し、必要な値を高速に得る

原点最適化と色マッチング

  • ソース画像を矩形領域の行列に分割する際、行列の原点は結果に影響する
  • 結果を最適化するため、アルゴリズムは画像原点周辺の9×19ピクセル領域内にあるすべての整数座標の原点について、画像全体の変換を繰り返す
  • 大量の処理量に対応するため、作業は利用可能な論理プロセッサに分散される
  • カラーパレットは、ユーザー設定に応じて標準ANSIパレット先頭8色から拡張ANSI256色全体まで制限できる
  • ソース画像を固有色平面に分離する際、パレット内で最も近い色を見つけるために、計算コストの高い CIEDE2000 知覚色差式を使用する

ソースコード

1件のコメント

 
GN⁺ 2024-06-08
Hacker Newsのコメント
  • このサイトでいちばんすごいページは カラーギャラリー だと思う: https://meatfighter.com/ascii-silhouettify/color-gallery.htm...

    • Wendy's のロゴはちょっと 不気味
    • Mastodon ロゴがないので、このページは無効
    • Z ロゴは本当に巧妙
      アイコンのグラフィックデザインを別の視点で見られる感じがする
  • コードにそのまま入れられる ゲームスプライト を作ろうとして、似たようなツールを作った: https://memalign.github.io/m/pceimage/index.html
    Webで動作し、色付きのASCII出力も編集できる
    ただし結果を良くするには Wobble を手動でオフにして、ピクセルサンプリングサイズを調整する必要があるので少し扱いが難しい

    • 本当に楽しくて気に入った
      おすすめとしては、揺れはなくしつつ、太くして角を丸めることで生まれる かわいらしさ は維持するモードがあるといい
  • ASCII系のアートが好きなら、GIFをASCIIに変換する アニメーションASCIIツール も気に入ると思う: https://www.gifcii.fun
    ちなみに自作したもの

    • GIF好きとしては本当に楽しい
      somehow 保存できるといいし、たとえば再びGIFや動画として書き出せたら素晴らしいと思う
  • Web版は Chromiumベースのブラウザ では最後まで進まないが、CLI版は動く: https://meatfighter.com/ascii-silhouettify/spa/index.html#/
    ついでに HN ロゴみたいに見える大きなASCIIアートも作ってみた

  • すばらしい作品で、色付きの Telnet Matrix を思い出した :)
    後になって https://ascii.theater/ も見つけた
    数年前、レトロコンピュータ用画像コンバータ向けに似たようなものを作ったことがあり、そのコンピュータの等幅フォントを使い、文字変換の前に ディザリング も適用していた
    写真からより滑らかなグラデーションが得られたからだ: https://github.com/KodeMunkie/imagetozxspec/blob/master/src/...

  • 「すでにあったものが再びあり、すでに行われたことが再び行われる。日の下に新しいものはない。」
    よくできている
    昔は EBCDIC と ASCII の文字の 印字密度 を利用して、誕生日バナーや絵を連続帳票用バンドプリンタ、その後はドットマトリクスプリンタでとても似た形で出力していたものだ

  • 今日は /etc/motd/etc/issue を編集する人がかなり増えそう

  • リアルタイムで動く 揺れる関数 で似たようなことをやってみた: https://piter-genuary2024.netlify.app/genuary9/

    • 標準ログの tail 出力から始めて、だんだん目に見えるパターンを混ぜていき、最終的にテキストの間から 怖い顔 が現れるような不気味なものを作れないか気になる
  • また npm か
    プロジェクトはすばらしいが、なぜわざわざこうしなければならないのかわからない
    普通のインストール方法はどこへ行ったんだろうと思う

    • どんな代替案を提案しているのか気になる
      NPM はどこでも同じように動作するし、NPM ほど多くのプラットフォームで広く使われているパッケージマネージャはない
    • ここで言う「普通のインストール」がどんな方式か教えてくれれば、その方式の問題を説明できる
    • インストールする必要すらない
      ただ npx で実行すればいい
    • そうだよね、普通のインストール方法がどうなったのか、あるいはそもそも存在したことがあるのかもわからない
      別のやり方で設定しようとすると何時間もかかって混沌とするので、自分のCLIリポジトリはあちこちで npm/yarn link でつないで使っている
      Python スクリプトですら nodemon main.py で開発しているが、必要なことを知っているのは Node 側の人たちだけな気もする
  • それでも Figma より https://asciiflow.com/# を使い続けると思う