2014/04/29

OS X Mavericksにmltermとlibsixelをインストールして端末で画像を表示する

OS X Mavericks 環境の端末で画像を表示したい一心で、端末界で評判の高いターミナルエミュレータ mlterm と Sixel 画像への変換ツール libsixel をビルド・設定したときのメモです。前置きがだいぶ長めです。

端末で画像を表示する動き

私は GNU Screen さえ満足に動けばターミナルエミュレータにはとくにこだわりは無く、OS X ですと Lion(10.7)までは Terminal.app で 256 色表示が出来なかったからという理由で iTerm を使い始めて現在に至っています。

ですがここ最近、端末で画像(Sixel Graphics)を表示する動きが観測範囲で散見されるようになりました。

そのスクリーンショットを見ると非常に気になるものの、何か特別な技を駆使して表示させているのだろうと思って遠くから眺めているだけでした。

そんなある日 @kefir_ さんが作成された Sixel Graphics への変換ツールとそれを GNU Screen で表示できるようにする Python スクリプトの存在を知りました。

仕組みや実装はサッパリ分かりませんが、これは試すしかありません。

RLoginで画像を表示してみる

libsixel の README を見ると RLogin でのスクリーンショットが多いのでまずは Windows 環境で試しました。

試すのは数日前に TL で見かけた画像。
% curl -s https://pbs.twimg.com/media/BOMrOo-CIAEVviz.jpg:large | img2sixel

(GNU Screen で表示する場合)
% curl -s https://pbs.twimg.com/media/BOMrOo-CIAEVviz.jpg:large | img2sixel | penetrate.py && cat -
あまりにもあっさりと表示できて感動しました。 GNU Screen 上から実行する場合は Sixel 画像データをターミナルエミュレータ側にパススルーさせていますので、当然ながら領域の分割等は無視されて表示されますがこれは仕方ないですね。

XTermで画像を表示してみる

libsixel を使って Sixel 画像が表示できるのは分かりましたが、それを確認するためだけに Windows が動作する仮想マシンを立ち上げるのも手間です。あらためて README の対応端末をよく見ると XTerm の名がありました。

OS X にインストールしている XQuartz(2.7.5)の XTerm は Patch #297 なので Sixel 画像には対応していそうですが、まだ試験的な扱いだからなのか -ti 340 オプションをつけても表示されませんでした。

ですが対応していることは分かりましたので、現時点の最新版 Patch #303 を --enable-sixel-graphics オプションをつけてビルドしたところ表示は出来ましたが 16 色しか出せずにぼやいていたところ、

私の勘違いを @kefir_ さんから指摘いただきました。そして紹介されたパッチを適用することで XTerm でも 256 色の Sixel 画像が表示できるようになりました。

(5/24追記)XTerm Patch 304 で ReGIS/Sixel 関連の実装に変更がありこのパッチは適用できなくなっています。また XQuartz(2.7.6)の XTerm Patch #303 でも Sixel 画像は表示できませんでした。

RLogin と XTerm で同じ GNU Screen のセッションにアタッチして同時に画像が描画されるのは面白いです。

そしてmltermへ…

これで Sixel 画像の表示を試すなら XTerm かなと思っていましたが、

という TeraTerm の中の人の一言。

その名は聞いたことがありましたが前述したとおりあまりターミナルエミュレータにこだわりが無かったので試そうとすら思っていなかったのですが、これは試すしかありません。

ですがちょうど試そうとしたときの mlterm のバージョン(3.3.4)に不具合があったようで、OS X 環境でビルドできず諦めかけていたところ、@uobikiemukot さんにパッチを作成頂いてどうにかビルドできました。 その後作者の @arakiken さんから連絡を頂いて、現在の最新版 3.3.5 ではこの問題は直っています。

mltermのインストール

(5/31追記) 以前の手順では configure 時のエラーを回避するためにシンボリックリンクを張っていましたがその手順は不適切でした。XQuartz 2.7.6 のファイルとバッティングして動作しません。CFLAGS で指定するように変更しました。XQuartz 2.7.5、2.7.6 で mlterm 3.3.5、3.3.6 のビルドを確認しています。

homebrew 環境へのインストールです。なのでソースを取得してコンパイルするだけです。

まず画像ファイルのロードに必要な画像処理ライブラリ gdk-pixbuf をインストールします。

% brew install gdk-pixbuf
==> Installing gdk-pixbuf dependency: gobject-introspection
==> Building source; bottle blocked by python requirement
==> Downloading http://ftp.gnome.org/pub/GNOME/sources/gobject-introspection/1.40/gobject-introspection-1.40.0.tar.xz
Already downloaded: /Library/Caches/Homebrew/gobject-introspection-1.40.0.tar.xz
==> ./configure --prefix=/usr/local/Cellar/gobject-introspection/1.40.0
==> make
==> make install
    /usr/local/Cellar/gobject-introspection/1.40.0: 219 files, 10M, built in 30 seconds
==> Installing gdk-pixbuf
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/gdk-pixbuf-2.30.7.mavericks.bottle.tar.gz
######################################################################    97.3%debug2: channel 0: window 999408 sent adjust 49168
######################################################################## 100.0%
==> Pouring gdk-pixbuf-2.30.7.mavericks.bottle.tar.gz
==> Caveats
Programs that require this module need to set the environment variable
  export GDK_PIXBUF_MODULEDIR="/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
If you need to manually update the query loader cache
  /usr/local/Cellar/gdk-pixbuf/2.30.7/bin/gdk-pixbuf-query-loaders --update-cache
==> /usr/local/Cellar/gdk-pixbuf/2.30.7/bin/gdk-pixbuf-query-loaders --update-cache
==> Summary
    /usr/local/Cellar/gdk-pixbuf/2.30.7: 209 files, 4.3M

画像の表示には直接関係ありませんが、アンチエイリアスされたフォントの描画に必要な cairo をインストールします。

% brew install cairo
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/cairo-1.12.16_1.mavericks.bottle.tar.gz
######################################################################## 100.0%
==> Pouring cairo-1.12.16_1.mavericks.bottle.tar.gz
   /usr/local/Cellar/cairo/1.12.16_1: 105 files, 7.6M

つぎに mlterm の最新版をダウンロードして解凍します。

% curl -L http://sourceforge.net/projects/mlterm/files/latest 2>/dev/null | tar xvzf -
x mlterm-3.3.5
x mlterm-3.3.5/man
x mlterm-3.3.5/man/Makefile.in
x mlterm-3.3.5/man/mlclient.1
x mlterm-3.3.5/man/mlterm.1

[...]

x mlterm-3.3.5/README
x mlterm-3.3.5/Makefile.in
x mlterm-3.3.5/LICENCE
x mlterm-3.3.5/ChangeLog
x mlterm-3.3.5/configure.in

そして --with-type-engines=cairo を付けて configure します。CFLAGS で freetype2 のライブラリがある場所を指定します。

私は野良ビルドを GNU Stow で管理しているのでそれ用に --prefix も指定します。

% cd mlterm-3.3.5
% ./configure CFLAGS="-I/opt/X11/include/freetype2" --with-type-engines=cairo --prefix=$HOME/local/stow/${PWD##*/}

[...]

Mlterm was configured as follows

Installation path prefix          : /Users/yoshikaw/local/stow/mlterm-3.3.5
Build shared libraries            : yes
Build static libraries            : yes
BiDi rendering (Fribidi)          : no
Indic rendering                   : no
External tools                    : mlclient mlcc mlimgloader
Image processing                  : yes
Built-in image library            :
utmp support                      : no
Type engines                      : cairo
DnD                               : yes
Input Methods                     : XIM kbd
Scrollbars                        : simple sample extra
libssh2                           : no
VT52                              : no

これで make するも freetype のヘッダファイルが見つからないというエラー。
% make

[...]

 gcc -I../../kiklib/include -I../../mkf/include -I/usr/X11/include -DUSE_TYPE_CAIRO -g -O2 -I/usr/local/include -I../../mlterm -c x_window_cairo.c  -fno-common -DPIC -o .libs/x_window_cairo.o
In file included from x_window_cairo.c:8:
In file included from /usr/X11/include/cairo/cairo-ft.h:46:
/usr/X11/include/ft2build.h:56:10: fatal error: 'freetype/config/ftheader.h' file not found
#include <freetype/config/ftheader.h>
         ^
1 error generated.
make[1]: *** [x_window_cairo.o] Error 1
make: *** [all] Error 2

XQuartz(2.7.5)には FreeType 2.5.0.1 が含まれていますので、その場所へのシンボリックリンクを作成します。
% sudo ln -s /opt/X11/include/freetype2/freetype /opt/X11/include/freetype

これで無事に make が最後まで通るようになりました。
% make

[...]

./comm.h:3:9: note: '_COMM_H_' is defined here; did you mean '_COMM_H'?
#define _COMM_H_
        ^~~~~~~~
        _COMM_H
1 warning generated.
gcc -o mlcc data.o main.o comm.o data_entry_string.o data_entry_bool.o data_entry_numeric.o data_entry_color.o data_entry_radio.o
gcc -I../../kiklib/include -g -O2   -c main.c
gcc -o mlclient main.o
cp mlclient mlclientx
あとは make install するだけです。
% make install
% cd ~/local/stow
% stow mlterm-3.3.5

ReGIS対応(5/2追記)

ReGIS(Remote Graphics Instruction Set) 形式の画像を表示するために sdl2、sdl2_ttf、fontconfig をインストールします。

私の環境では fontconfig は既にインストールされていました。

% brew install sdl2
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/sdl2-2.0.3.mavericks.bottle.tar.gz
######################################################################## 100.0%
==> Pouring sdl2-2.0.3.mavericks.bottle.tar.gz
    /usr/local/Cellar/sdl2/2.0.3: 75 files, 3.9M
% brew install sdl2_ttf
==> Downloading http://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.12.tar.gz
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/sdl2_ttf/2.0.12
==> make install
    /usr/local/Cellar/sdl2_ttf/2.0.12: 8 files, 100K, built in 14 seconds
% brew install fontconfig
Warning: fontconfig-2.11.1 already installed
configure オプションは同じです。最後の出力の External tools のところに registobmp が表示されていれば ReGIS(の一部コマンド)が使用できるようです。
% ./configure CFLAGS="-I/opt/X11/include/freetype2" --with-type-engines=cairo --prefix=$HOME/local/stow/${PWD##*/}

[...]

Mlterm was configured as follows

Installation path prefix          : /Users/yoshikaw/local/stow/mlterm-3.3.5
Build shared libraries            : yes
Build static libraries            : yes
BiDi rendering (Fribidi)          : no
Indic rendering                   : no
External tools                    : mlclient mlcc mlimgloader registobmp
Image processing                  : yes
Built-in image library            :
utmp support                      : no
Type engines                      : cairo
DnD                               : yes
Input Methods                     : XIM kbd
Scrollbars                        : simple sample extra
libssh2                           : no
VT52                              : no

% make && make install

mltermの設定

まずはあらかじめ用意されている設定ファイルをコピーします。

% cp -rp $HOME/local/etc/mlterm ~/.mlterm
そして README を見ながら必要な箇所を自分の環境に合わせます。 以下は私の環境での設定です。正確にはどうするかよく理解できていないフォントについては、アンチエイリアス前提ですので aafont に 1 行だけ書いています。
% /usr/bin/grep -h '^[^# ]' ~/.mlterm/main
use_bidi = false
col_size_of_width_a = 2
use_multi_column_char = true
fontsize = 14
use_anti_alias = true
scrollbar_view_name = next
% /usr/bin/grep '^[^# ]' ~/.mlterm/*font
/Users/yoshikaw/.mlterm/aafont:DEFAULT=Ricty for Powerline

mltermで画像を表示してみる

libsixelで変換したSixel画像

今までの例と同じく curl でダウンロードした画像ファイルを libsixel で Sixel 画像に変換したもの。GNU Screen で表示するために penetrate.py を使います。

Ghostscriptで変換したSixel画像

別の例として Ghostscript で PostScript ファイルを Sixel 画像に変換して表示したもの。

% gs -q -r80 -dNOPAUSE -dBATCH -sDEVICE=ln03 -sOutputFile=- ~/local/src/screen-4.2.1/doc/fdpat.ps
例にある fdpat.ps は GNU Screen の exec コマンドで使用するファイルディスクリプタの組合せの図。この例は GNU Screen 内ではうまく表示できませんでした。
Sixelのスケーリングモード拡張(5/2追記)

スクリーンショットを取る都合上 Ghostscript の例は縮小していますが、ご覧の通り文字がつぶれています。変換を重ねたものだから仕方ないのかなと思っていましたが、

ということらしいのでさっそく RLogin で試したところ、端末幅に合わせてキレイに出力されました。(このサイズでは分かりづらいですが、もう少し大きくすると普通に文字が読めるようになります)

gnuplotで出力したReGIS形式の画像(5/2追記)

homebrew でインストールした gnuplot は ReGIS 形式の出力には対応しているようですが、配布物に含まれる demo がインストールされません。そこで @kefir_ さんが Sixel 画像出力のデモ用に用意されている Makefile を使用して、gnuplot の配布物の取得と Sixel Graphics 対応の gnuplot をビルドします。

% mkdir ~/work/gp
% cd !$
% curl -s -O https://gist.githubusercontent.com/saitoha/8539548/raw/034f6a99467d9501a6c3ad4bc547a192834c33ed/Makefile
% make gnuplot/src/gnuplot
curl 'http://gnuplot.cvs.sourceforge.net/viewvc/gnuplot/gnuplot/?view=tar' | tar xz

[...]

gcc -rdynamic -fPIC -I../../src -g -O2 -shared -L/usr/X11/lib -L/usr/local/opt/jpeg/lib -o demo_plugin.so demo_plugin_so-demo_plugin.o  -liconv
make[4]: Nothing to be done for `all-am'.
Creating binary data files
Making all in tutorial
make[3]: Nothing to be done for `all'.
Making all in share
cp -p ./Gnuplot.app-defaults Gnuplot
make[3]: Nothing to be done for `all-am'.

make が終わったら demo ディレクトリに移動して homebrew の gnuplot で ReGIS 形式の出力を確認します。

% cd gnuplot/demo
% /usr/local/bin/gnuplot -e 'set term regis' world2.dem
せっかくなのでビルドした gnuplot で Sixel 画像の出力も試してみます。
% ../src/gnuplot -e 'set term sixel' world2.dem
こうやって mlterm 上で見比べた感じでは、ReGIS 形式は当時の端末に合わせた?ベクタ画像言語なので横長に表示され、ビットマップ形式の Sixel 画像だと表現力が高いというイメージがあります。

VT330 実機での ReGIS 形式の画像出力の動画を見ると、さすがに描画は遅いですが端末のサイズに合わせてキレイに表示されていますね。

libsixelのlibcurl integration(5/24追記)

これまでは Sixel 画像を表示するために curl でダウンロードした画像ファイルを img2sixel コマンドに標準入力として渡していましたが、libsixel 0.19.1 で curl の機能が統合されました。

この機能は configure 時に --with-libcurl と指定しないと有効になりません。

なお homebrew で導入した curl では pkg-config の設定は行われません。

% brew install curl
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/curl-7.37.0.mavericks.bottle.tar.gz
Already downloaded: /Library/Caches/Homebrew/curl-7.37.0.mavericks.bottle.tar.gz
==> Pouring curl-7.37.0.mavericks.bottle.tar.gz
==> Caveats
This formula is keg-only, so it was not symlinked into /usr/local.

Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/curl/lib
    CPPFLAGS: -I/usr/local/opt/curl/include

==> Summary
    /usr/local/Cellar/curl/7.37.0: 75 files, 2.1M
% pkg-config --libs libcurl
Package libcurl was not found in the pkg-config search path.
Perhaps you should add the directory containing `libcurl.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libcurl' found
% PKG_CONFIG_PATH=/usr/local/opt/curl/lib/pkgconfig pkg-config --libs libcurl
-L/usr/local/Cellar/curl/7.37.0/lib -lcurl

そのため PKG_CONFIG_PATH 環境変数を設定するか、LIBCURL_LIBSLIBCURL_CFLAGS を指定して configure する必要があります。ここではせっかく用意されているので後者を選びます。

% LIBCURL_LIBS="-lcurl -L/usr/local/opt/curl/lib" LIBCURL_CFLAGS="-I/usr/local/opt/curl/include" ./configure --with-libcurl

[...]

libsixel was configured as follows

       Loader component    : stb_image
       libcurl integration : yes


% make && make install
libcurl integration によってコマンドラインがスッキリしました。

おわりに

端末に画像を表示するだけでも楽しいのですが、システムが生成する各種データの可視化が端末で手軽に出来るようになるともっと面白くなりそうです。(以下は FreeBSD の GEOM 情報の Graphviz 出力を Sixel 画像に変換したもの)

端末で画像を表示する別のアプローチとして、ユーザ定義外字(DRCS)として画像を表示する動きもあるようです。

引き続き端末界の観測を続けてゆこうと思います。

0 件のコメント:

コメントを投稿