4 ポイント 投稿者 GN⁺ 2024-06-08 | 1件のコメント | WhatsAppで共有
  • lsixは、lsのように現在のディレクトリや指定したファイル一覧を対象に、画像をターミナル内にサムネイルとして表示するBashスクリプトで、出力にはSixelグラフィックスを使用する
  • ImageMagickを使って複数の画像形式を処理し、GIFや複数画像を含むファイルをコマンドラインで指定すると、フレームを展開してモンタージュとして表示する
  • ターミナルのSixel対応状況、前景色・背景色、カラー・レジスタを拡張できるか、ウィンドウ幅を検出し、サムネイル品質と配置を調整する
  • インストールはlsixファイルをパス上に置き、ImageMagickを用意すればよい。macOSではbrew install lsixでImageMagickも一緒にインストールできる
  • XTermはデフォルトでSixelモードがオフになっており、一部のターミナルは互換性がないため、実際に使う前にSixel互換ターミナルか確認する必要がある

lsのように使えるターミナル画像一覧ツール

  • lsixは画像用のlsに近いツールで、ターミナル内にファイルのサムネイルをインライン表示する
  • 基本的な実行方法はシンプル
    • lsixだけを入力すると、現在の作業ディレクトリ内の画像を表示する
    • lsix [ FILES ... ]形式でファイル名を指定できる
    • シェルのワイルドカードを使えるため、lsix *jpg * pngのように実行できる
  • 出力にはSixelグラフィックスを使用する

ImageMagickベースの形式処理と表示方法

  • ImageMagickを使用するため、さまざまな画像形式をサポートする
  • PDFのようにレンダリングが遅くなり得る形式は、明示的に要求しない限り表示しない
    • 特定の形式を強制的に列挙するには、ファイル名を直接指定するか、*.pdfのようなワイルドカードを使用する
  • GIFまたは複数の画像を含むファイルをコマンドラインで指定すると、すべてのフレームを展開してモンタージュとして表示する
    • GIFは一部のフレームについて、前のフレームとの差分ピクセルだけを保存している場合がある
  • ビットマップではないグラフィックスも動作する場合がある
    • 例: .svg.eps.pdf.xcf

ターミナル環境の検出機能

  • lsixは制御シーケンスを使って、ターミナルがSixelグラフィックスをインライン表示できるかを検出する
  • PNGとSVGのアルファチャンネルはターミナルの背景色に合わせて処理される
    • lsixはターミナルのエスケープシーケンスで前景色と背景色を取得しようとする
    • 前景色はテキストの塗りつぶし色に使われる
  • xtermのようにカラー・レジスタ数を増やせるターミナルを検出すると、画像品質を高めるために自動で拡張する
  • dtterm WindowOpsをサポートするターミナルでは、ウィンドウ幅に合わせて1行あたりのタイル数を調整する
  • ディレクトリ内に画像が多い場合は、モンタージュ全体の生成を待たないように処理する
    • 画像が21個超の場合は1行ずつ表示する
  • ファイル名が長すぎる場合は、ImageMagickのmontageに渡す前にテキストを折り返す
    • lsixなしでmontageを使うと、長いファイル名が互いに重なることがある
  • Unicodeファイル名は、使用するフォントにグリフがあれば動作する

インストールと設定方法

  • インストールはlsixファイルを/usr/local/binのようなパスに置いて実行すればよい
  • lsixはBashシェルスクリプトである
  • 必須ソフトウェアはImageMagickのみ
    • 例: apt-get install imagemagick
  • macOSユーザーはbrew install lsixを使用できる
    • 必要な場合はImageMagickも一緒にインストールされる
  • 現在の設計は非常にシンプル
    • コマンドラインフラグなし
    • 設定ファイルなし
    • 調整用ノブなし
  • タイル幅、フォントファミリー、ポイントサイズなどの値は、ファイル先頭の変数を変更することで変えられる
    • インストール済みフォント一覧はconvert -list fontで確認できる

Sixel対応ターミナルの要件

  • ターミナルはSixelグラフィックスをサポートしている必要がある
  • 単一画像をSixelとして出力し、ターミナルをテストできる
convert foo.jpg -geometry 800x480 sixel:-
  • 開発にはxtermのvt340エミュレーションモードが使われた
  • XTermはデフォルトではSixelモードが有効になっていない
    • 起動時にxterm -ti vt340を使用できる
    • または.Xresourcesxterm*decTerminalID : vt340を追加し、xrdb -merge .Xresourcesを実行できる
  • Fedoraのような一部のディストリビューションでは、xtermがSixel対応なしでコンパイルされている場合がある
    • この場合はfootまたはmltermのような代替ターミナルを試せる

互換ターミナルと非互換ターミナル

  • Sixel互換ターミナルとして確認または報告されているもの
    • XTerm、MLterm、foot、Wezterm、Contour、Apple MacOS向けiTerm2、Yaftはテスト済み
    • Konsole、yakuake、Microsoft Windows向けWSLtty、Cygwin向けMinTTY、VTEの特殊コンパイル、sixel-tmux、ttydは報告あり
  • Sixel非互換ターミナル
    • MacOS Terminal、kitty
    • 標準のlibvteベースのターミナル
      • gnome-terminal
      • terminator
      • lxterm
    • Alacrittyはパッチを適用すると動作する場合がある

既知のバグと制約

  • XTermのreverse videoモードであるxterm -rvは、前景色と背景色を明示的に指定することとは異なる
    • 明示指定は検出する方法があるが、reverseVideoリソースは検出できないため、背景色が誤る可能性がある
  • XTermの画面幅は現在1000pxに制限されている
    • 1000x1000より大きい画像をxtermが処理できるようになれば、制限を取り除く予定
    • 最後のテストはXTerm(344)基準
  • @で始まるファイル名はImageMagickで特別扱いされる
    • lsix ./@foo.pngのようにディレクトリを前に付ける必要がある
    • これはlsixではなくImageMagickのバグである
  • 空文字列""をファイル名として指定するとImageMagickが停止する
    • ImageMagickのバグまたは不正な動作と思われる
  • 長いファイル名の折り返しは動作するが、賢くはない
    • 空白、ダッシュ、アンダースコア、ピリオドを基準にした折り返しはまだ実装されていない
  • コマンドラインにディレクトリを指定すると、ユーザーがそのディレクトリにcdしたかのように処理する
    • 再帰処理は難しくないが、シンプルなスクリプトにコマンドラインフラグを追加することを避けている
  • lsix foo.aviの実行は問題を引き起こす可能性がある

Sixel標準と実装上の限界

  • Sixel標準には、グラフィック画面サイズを問い合わせる方法がないように見える
  • VT340文書を基準にすると、プログラムはレンダリング対象デバイスの解像度をあらかじめ知っている必要がある
  • XTerm 344は、この問題を解決する制御シーケンスCSI ? Pi ; Pa ; Pv Sを追加した
    • mltermのような一部のターミナルはまだ実装していない
  • dtterm WindowOps拡張でウィンドウサイズを読む代替手段がある
    • Sixelグラフィック画面のジオメトリとウィンドウサイズが必ずしも同じではないため、正確な解決策ではない
    • 例えばxtermは、ウィンドウがより大きくてもグラフィックジオメトリを1000x1000に制限する
  • どちらの方法も失敗した場合、lsixはVT340環境と仮定する
    • 解像度は800x480
    • 1行にタイルが6個だけ入るとみなす
  • Sixel標準は、利用可能なカラー・レジスタ数を問い合わせる方法も提供していない
    • lsixはxterm拡張を使用する
    • ターミナルが応答しない場合は元のVT340と仮定し、16個のカラー・レジスタだけを使用する

libsixelを使わない理由

  • libsixelは、最適化されたSixelグラフィックスコマンドを出力するプロジェクトである
  • lsixはlibsixelの代わりにBashとImageMagickを使用する
    • BashとImageMagickが広く存在し、どこでも簡単に動作するようにするための選択である
    • スクリプトをシンプルに保ち、ユーザーが容易に修正・拡張できるようにする
    • ImageMagickはlibsixelのimg2sixelが使用するstb_imageよりも多様な入力形式を読み取れる
      • 例: xpm、svg、16-bit png、sixelファイル
    • ImageMagickは入力を読み取り、Sixel出力を直接書き出せる
    • libsixelの方が高速な場合はあるが、単純なディレクトリ一覧表示にはImageMagickでも十分に速い

参考資料

1件のコメント

 
GN⁺ 2024-06-08
Hacker Newsのコメント
  • 私のように tmux なしではターミナルが使いづらい なら、実験的だった Sixel ブランチが約10か月前についにマージされた
    いまではメインラインの tmux を --enable-sixel 付きでビルドすれば、tmux 内で lsix のようなツールを使える
    お気に入りのターミナルやターミナルマルチプレクサが Sixel をサポートしているか知りたければ、「Are We Sixel Yet」を見るとよい
    https://github.com/tmux/tmux/commit/dfbc6b1888c110cf0ade66f2...
    https://www.arewesixelyet.com

    • 数年前に Zellij に乗り換え、2022年のある時点から Sixel サポートを便利に使っている
      ワークフローを変えてみたいなら、標準状態で tmux よりずっと良い体験だと思う
      以前なら外部プラグインや複雑な設定スクリプトで追加していた機能が最初から入っていて、安定性も性能もずっと良かった
      https://zellij.dev/
    • tmux の用途がいまいちよく分からない
      なぜワークフローの 必須ツール になるのか、そして私の作業でもなぜ必須になり得るのか説明してもらえる?
    • でも、そもそもなぜ必要なのか? ピクセルグラフィックをわざわざ テキストベースの低解像度グリッド に押し込む理由はあるのか? そのままピクセルグラフィックを使えばいいのでは?
    • かなり前から tmux を使っていて、その前は screen を使っていたが、Sixel がなぜ大きな違いになるのかよく分からない
      現在のタイル型のやり方に対して tmux にスタック型ウィンドウマネージャを持ち込むくらいの変化なのか? それとも単にターミナルグラフィックが良くなるだけなのか? 私は完全に勘違いしている?
      もし単にグラフィックが良くなるだけなら、なぜ tmux が対応する必要があるのかよく分からないし、Gnome Terminal のようなターミナルエミュレータ側のほうが重要に思える。両方必要なのかもしれないが、tmux はただ素通しすればよいのだと思っていた
    • brew で tmux をインストールすると Sixel が有効 になるか知っている人はいる?
  • このリポジトリでいちばん気に入った機能は README.md.d ディレクトリだ
    かなり良いアイデアで、わざわざ .md を付けなくてもよさそう

    • 本当に強い一手は、README ファイルの中に画像を そのまま Sixel として埋め込む ことだ
      そうすれば cat README するだけで画像がそのまま見えるかもしれない
  • "\e[c" を使って Sixel サポートの有無を自動検出 している
    https://github.com/hackerb9/lsix/blob/3a431793a747df3f934051...
    "\e[c" は "send device attributes" のこと
    https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-F...

  • アイデアは素晴らしいが PuTTY/KiTTY では動かない
    $ lsix を実行すると、ターミナルが Sixel グラフィック対応を報告していないというエラーになり、xterm -ti vt340 のような Sixel 対応ターミナルを使うか、ターミナル作者に対応を依頼するよう表示される
    単一画像は convert foo.jpg -geometry 800x480 sixel:- でテストでき、実際に対応しているターミナルなら http://github.com/hackerb9/lsix/issues にバグ報告してほしいと案内される
    デバイス属性コードは ^[[?6c と表示される
    残念だ。かなり良さそうだったのに。Sixel をサポートする オープンソースの Windows ターミナル はあるのだろうか? 多くは Cygwin や WSL 向けに見え、純粋な Windows 用はあまり見当たらない

    • 最近 wezterm を使い始めたが、かなり気に入っている
      クロスプラットフォームで、Sixel グラフィックをサポートしている
      https://github.com/wez/wezterm
    • Mintty は Sixel をサポートする優れた Windows ターミナルだ
  • 似た系統のものとして timg もある: https://github.com/hzeller/timg

  • MacOS 向けの iTerm2 には似た機能が内蔵されていて、サーバー側の負担はさらに少ない
    サーバー側で大量の画像ライブラリを使って画像を Sixel にレンダリングする代わりに、画像全体を base64 エンコードしてクライアントに送り、クライアントが画像形式を判別してターミナル上でローカルにレンダリングする
    https://iterm2.com/documentation-images.html

    • konsole も同じプロトコルを実装している
      Linux では無改変の imgcat スクリプトをそのまま使っている
      ImageMagick で変換するより当然ずっと速いが、とりあえず lsixbin ディレクトリに入れてある
  • 信頼できないディレクトリで実行するときは注意が必要
    特に PDF のように画像をパースするものは、他のツールと同様に危険になり得るし、ImageMagick を使う場合はなおさら注意が必要だ

    • 信頼できない画像をパースすること自体が本質的に問題なのか?
      信頼できないダウンロードフォルダを Gnome Files で開いたときに中の画像を表示し、その結果としてパースするなら、気にすべきセキュリティ問題なのだろうか?
      PDF 内の JavaScript のようなものは問題になり得ると思っていたが、単なるプレビューまで危険だとは思っていなかった
  • 使っているターミナルが Sixel グラフィック をサポートしている必要がある

    • Sixel をサポートしないターミナル向けのグラフィックライブラリを作った
      https://github.com/dheera/python-termgraphics
      このライブラリを改造してフォールバック経路として対応させれば面白いかもしれない
    • xterm は Sixel をサポートしているのだから、TERM=xterm256-color のような値を設定すれば全部互換ということになるよね……そうだよね? gnome-terminal
    • mlterm では動く
  • fzf は 0.44.0 からプレビューウィンドウで実験的な Sixel 画像サポートを提供している
    Windows では使えない
    https://github.com/junegunn/fzf/releases/tag/0.44.0
    fzf --preview='fzf-preview.sh {}'

    • 代わりに fzf --preview 'convert {} -geometry 800x480 sixel:-' を使える
      これにも ImageMagick のインストールが必要