高速イメージビューア sxiv を使うことのメモ

シンプルで軽い sxiv : Simple X Image Viewer

sxiv_image_viewer_000.jpg

画像ビューアは沢山あるけれど、CLI(TUI)中心の利用で素早く扱えるものがないかと探していたところ sxiv を知るに至った。

GitHub – muennich/sxiv: Simple X Image Viewer

sxiv とは

sxiv は C で書かれた軽量な画像ビューアで、ひとことで評するならばシンプルだけれどやるべきことはうまくて素早い画像ビューア、ということだろう。

その名の意味するところは “Simple or Small or Suckless X Image Viewer” だという。 feh や qiv よりさらにシンプルでかつ gtk に依存せず、そしてタイル型ウィンドウマネージャなんかでうまく動くものを目指して作られた、とされる。

なにより画像を高速に表示することを目指しており、爆速である。その分なのか基本機能は至ってシンプルで、多機能なGUIのイメージビューアに比べるとその恐ろしく絞り上げた様は精悍でさえあるように思う。

機能としては、基本的な画像ファイルの表示と、アニメGIFなどのマルチフレーム対応としてアニメーション再生およびフレーム毎の表示が可能である。またイメージ単体の表示に加え、サムネールを並べて選択できるようなブラウザ機能(サムネールモード)があり、ENTERキーで容易に切り替えができる。このサムネール表示にはキャッシュを使うから再表示でもたつかない。

操作は vim ライクなものでわかりやすくなっている。また、シェルスクリプトなどで外部ファイルにキーハンドラを記述することで機能を拡充でき、同じくスクリプトによりステータスバーもカスタマイズ可能である。

ともかく、シンプル、軽量、高速ゆえに他のコマンドや自前スクリプトとの組み合わせもやりやすい。そういうような使われ方で真骨頂を発揮するのだろう。

sxiv のインストール

Ubuntuや Arch Linux ではバイナリリポジトリにあるものをインストールできる。

## Ubuntu
$ sudo apt install sxiv
## ArchLinux
$ sudo pacman -S sxiv

ソースをとってきてコンパイルするということであれば、設定用ソースの一部を書き換えてキーバインドなどを変更できる。

sxiv の起動

sxiv の起動はファイル名の渡し方によっておおまかに3つに分けられる。

まずは基本の、画像ファイル名を指定する方法。リストを与えることで複数の画像ファイルを読み込む。

## リストを渡す
$ sxiv hoge.jpg &
$ sxiv foo.jpg bar.jpg baz.jpg &

ディレクトリを指定するとディレクトリ内の表示可能な画像ファイル全てを読み込むようになる。

## ディレクトリ指定
$ sxiv ~/Pictures/wallpapers &

-i オプションを指定すると標準入力からリストを受け取るようになる。

## リストを標準入力へ渡す
$ ls ~/Pictures/*.jpg | sxiv -i &

起動方法がわかったなら、ちょっと操作してみよう。

起動するとまずはエントリの最初の画像が表示される。この状態が「イメージモード」である。

sxiv_image_viewer_image-mode.jpg

n で次の画像を表示、 p で逆に進む。

f を押すとフルスクリーン表示になる。もう一度押せばもとに戻る。

そして <enter> でウインドウの中にサムネールが並ぶ「サムネールモード」に切り替わる。

sxiv_image_viewer_thumbnail-mode.jpg

j k h l でカーソルを移動して <enter> でその画像を表示、つまり「イメージモード」に戻る。

ところで、前述のディレクトリ指定の方法では指定階層にあるファイルのみ表示されるが、 -r オプションで再帰的に探索するようになる。

$ sxiv -r ~/Picutres &

最初からサムネールモードで実行するには -t を指定する。また、フルスクリーンは -f 。これらを組み合わせて、

$ sxiv -tfr ~/Pictures &

とすると最初からサムネールモードでフルスクリーン表示してくれる。エイリアスを設定しておくといいかもれない。

sxiv の起動オプション群はコマンド連携のニーズに十分応えるものだろう。詳細は man page sxiv(1) を参照のこと。

sxiv の使い方

イメージモードの操作

  • イメージをめくる
    Pre キー操作 機能 他のキー
    <n> n 次の画像を表示する <space>
    <n> p 前の画像を表示する <backspace>
      g 最初のイメージへジャンプする  
    <n> G 最後のイメージ あるいは <n>番めのイメージへジャンプする  
    <n> [ 10個前の画像 / (<n>×10)個前の画像  
    <n> ] 10個先の画像 / (<n>×10)個前の画像  
    <n> s スライド表示開始/停止 (表示間隔を<n>で指定可能)  
      f フルスクリーン表示にする/しない  
      b ステータスバーを表示する/しない  
      D 画像を表示候補から削除  
      <enter> サムネールモードへ切り替える  
      q 終了する  

    なお、 Pre 欄に <n> とあるものは、コマンドの前に数字を入力することでステップ値を与えられるもの。例えば 3n と打てば3つ先の画像を表示し、 12G と打てば最初から12番目のイメージにジャンプする。

  • イメージのスクロール
    Pre キー操作 機能 他のキー
    <n> j 下へスクロール(画面の1/5ずつ) <down>
    <n> k <up>
    <n> h <left>
    <n> l <right>
      C-j 1画面分下へスクロール C-<down>
      C-k 1画面分上 C-<up>
      C-h 1画面分左 C-<left>
      C-l 1画面分右 C-<right>
      J 下端までスクロール  
      K 上端  
      H 左端  
      L 右端  
  • イメージのズームと回転
    Pre キー操作 機能
      + ズームイン
      - ズームアウト
    <n> = 100% あるいは <n>% の大きさにする
      w 100%もしくはウィンドウの大きさにあわせる
      W ウィンドウの大きさに合わせる
      e ウィンドウ幅にあわせる
      E ウィンドウ高にあわせる
      > イメージを時計回りに90度回転
      < イメージを反時計回りに90度回転
      ? イメージを180度回転
      イメージを左右反転
      _ イメージを上下反転
      r 画像をリロード (回転や反転をキャンセル)
  • イメージ表示の調整
    Pre キー操作 機能
    <n> } ガンマ補正値を増やす(明るくなる)
    <n> { ガンマ補正値を減らす(暗くなる)
      C-g ガンマ補正値を元に戻す
      a アンチエイリアス表示する/しない
  • マルチフレームイメージ(アニメGIFなど)の操作
    キー操作 機能
    C-n 表示イメージを次のフレームにする
    C-p 表示イメージを前のフレームにする
    C-<space> アニメーションを再生/停止
  • マーク
    Pre キー操作 機能
      m マークする/マークを解除する
      M マークを反転
      C-m マークを全て解除
    <n> N マークした画像へジャンプ(次)
    <n> P マークした画像へジャンプ(前)

    マーク機能は非常に単純なものであり、 sxiv を終了するとその内容はリセットされる。そのままでの使い方としては、とりあえずマークしておいてマークジャンプで連続して眺める、というくらいのものだが、外部キーハンドラによるカスタマイズでその威力を発揮する(後述)。

    また、起動オプションに -o を指定すると sxiv の終了時にマークしたファイルのリストを標準出力へ渡してくれるので、イメージファイルを眺めながらの絞り込み機能が実現できる。

    $ sxiv "hoge.jpg" "fuga.jpg" "piyo.jpg" -o
    ## sxiv上で fuga.jpg にマークして終了
    fuga.jpg
    

    sxiv は -i オプションで標準入力からファイル名を受け取るようになるが、パイプで find なんかの結果を渡すとすると以下のようになるだろうか。

    $ find -type f -name *.jpg | sxiv -i -o
    

    こんなような感じで使うと、さながらヴィジュアルフィルタといったような動作になる。

サムネールモードの操作

  • サムネールモードの基本操作
    Pre キー操作 機能 他のキー
    <n> h カーソルを左へ <left>
    <n> j カーソルを下へ <down>
    <n> k カーソルを上へ <up>
    <n> l カーソルを右へ <right>
      + ズームイン  
      - ズームアウト  
      R サムネールをリロードする  
      f フルスクリーン表示にする/しない  
      b ステータスバーを表示する/しない  
      D 画像を表示候補から削除  
      <enter> イメージモードへ切り替える  
      q 終了する  

    ガンマ補正やアンチエイリアス、マークについてもイメージモードと同様のキーで操作できる。

  • サムネールファイル

    sxiv はサムネールを ~/.cache/sxiv の下に作成する。元画像がなくなったサムネールを削除するには以下のように -c オプションで sxiv を実行する。

    $ sxiv -c
    

    また ~/.cache/sxiv 下は、元画像のあったディレクトリと同様の構成が再現されており、空になったサブディレクトリだけを削除するには以下のコマンドを利用するといいと man page に記述がある。

    $ cd ~/.cache/sxiv
    $ find . -depth -type d -empty ! -name '.' -exec rmdir {} \;
    

sxiv をサンプルスクリプトでカスタマイズする

ステータスバーの表示内容

sxiv のステータスバー(ウィンドウ下端)左寄りにはファイル名が表示されているだけだが、この表示内容は ~/.config/sxiv/exec/image-info にスクリプトを書くことでカスタマイズが可能である。

公式のサンプル sxiv/image-info (GitHub) が用意されており、このスクリプトを使うとステータスバーに ファイルサイズ、画像サイズ、タグ、ファイル名 が表示されるようになる。

なお ‘タグ’ は次項キーハンドラのサンプルスクリプトなどで IPTC 情報にタグを書き込んだ場合のもので、その表示には identify (ImageMagick) が必要である。

外部キーハンドラでキーコマンドを追加する

sxiv はキーイベントのハンドラを ~/.config/sxiv/exec/key-handler に置くことで、キーコマンドを定義できる。デフォルトのキーイベントは C-x だ。 Emacs みたいに C-x をプレフィクスキーとするキーバインディングが可能だ。

これも sxiv/key-handler (GitHub) にサンプルがあり、機能は以下の通り。

キー操作 機能 依存コマンド
C-x y ファイル名をコピー xclip
C-x C-c 画像をコピー xclip
C-x C-e メタデータ表示(Exif / IPTC / XMP) rxvt-unicode, exiv2, less
C-x C-g Gimp で開く gimp
C-x C-, 画像を反時計回りに回転 jpegtran / mogrify (ImageMagick)
C-x C-. 画像を時計回りに回転 jpegtran / mogrify (ImageMagick)
C-x C-/ 画像を逆さまにする jpegtran / mogrify (ImageMagick)
C-x C-t タグを追加する dmenu, iptckwed
C-x M-t タグを削除する dmenu, iptckwed

このスクリプトでの画像回転機能は、画像を回転してファイルを書き換えるものである。

また、タグ作成機能は画像ファイルにメタデータ(IPTC)として書き込むものである。これに必要な iptckwed というコマンドは IPTC keyword editor のこと。 AUR – iptckwed-git にも登録がある。書き込まれたタグは ‘メタデータ表示’ で表示できるが、前項のステータスバーのサンプルスクリプトでも表示されるようになる。

なお、これらのコマンドは全てマーク機能と組み合わせて使えるように配慮されている。例えば複数の画像にマークしてファイル名をコピーすると、スペース区切りのファイル名リストをコピーバッファに取り込む。画像回転も複数のファイルでいっぺんに行える(サムネールモードを使うとわかりやすい)し、Gimpも複数のファイルを開ける(開き過ぎに注意)し、タグもまとめてつけたり消したりできる。

sxiv から壁紙を設定する

sxiv で画像を管理しながら、気に入ったイメージがあったらすばやく壁紙設定できるととても便利だろう。しかし sxiv には壁紙設定機能はない。だったら前述のキーハンドラにスクリプトを書いて feh で壁紙を設定するようにしてみてはどうか。

"W")  read f && feh --bg-fill "$f" ;;

さきほどのサンプルスクリプト sxiv/key-handler (GitHub) の case 文内に上記の一行を付け加えると、 C-x W で表示中の画像を壁紙設定できるようになる(要 feh)。

キーハンドラは最初の引数( $1 )で C-x の後に押すキー内容を受け取り、標準入力にてファイル名のリスト(改行区切り)を受け取る。マーク機能で複数ファイルのリストが与えられることもあるが、壁紙設定は1つの画像しか受けつけないのだから、単純に read で最初の1ファイル分だけ読み取って feh へ渡すようにした。

feh の壁紙設定機能は --bg-fill オプションでアスペクト比を維持しつつ余白が無くなるようズームしてクロップする。余白を許してクロップしないなら --bg-max を使う。ほかにも center や scale 、 tiling なんかもある(詳細は FEH(1) )。

また、 feh で壁紙設定をするごとに ~/.fehbg という小さなシェルスクリプトファイルが作成/更新され(最初から実行属性あり)、そこには実行すると設定時のスケールで壁紙が表示されるよう書かれている。デスクトップ環境のスタートアップスクリプトに ~/.fehbg の実行を書き加えておけば、最後に設定した壁紙がデスクトップ起動時に表示されるという寸法だ。

sxiv と TMSU を使い画像をタグで管理する

軽くて速い sxiv は大量の画像を確認するのに最適で重宝する。だが、一方でそれら大量の画像を整理するツールが必要である。

ざっくりとディレクトリで分けて管理するにはファイルマネージャで整理することだろう。 CLI では ranger のように軽快な TUI ファイルマネージャがいい。

しかし、例えばお気に入りや使用用途、あるいは人物や事物、場所などといったカテゴリーで多元的に管理するには一意のディレクトリだけでは難しいところもある。ならば「タグ」づけする方法ならどうだろうか。

CLI で使えるタギングシステムもいくつか実装があるようだが、ここでは導入が手軽で扱いやすい TMSU をとりあげる。

TMSU はタグ情報を独自のデータベースに格納するタイプのもので、音楽ファイルや画像ファイルの管理に使われることも多いようである。前述のキーハンドラサンプルにあったタグはIPTC情報を書き換えるものだが、こちらは対象ファイルを改変することはない。

この TMSU タグを sxiv からつけられるようにすれば、画像整理がやりやすくなるだろう。

tmsu コマンド

TMSU の使い方は 公式ページ に書かれてあるものがわかりやすい。

TMSU のコマンドはサブコマンドとオプションを組みわせるタイプだ。ここでは簡単な例を示すが、さらなるオプションの組み合わせで色々とできる。詳しくは help や man を参照されたし。 tmsu help <sub_command> でサブコマンドごとに表示されるヘルプが、わかりやすい。

## タグをつける:  tmsu tag <file> <tag> ...
tmsu tag ~/Wallpapers/mt_fuji.jpg landscape
tmsu tag frog.jpg nature animal
## タグをはずす:  tmsu untag <file> <tag> ...
tmsu untag ~/Wallpapers/mt_fuji.jpg landscape
tmsu untag frog.jpg animal
## タグ一覧:  tmsu tags [ <file> ... ]
tmsu tags
tmsu tags ~/Wallpapers/mt_fuji.jpg
tmsu tags ~/Pictures/*
## タグづけしたファイルの一覧: tmsu files [ <tag> ... ]
tmsu files
tmsu files nature animal
tmsu files landscape or nature
## タグ削除: tmsu delete <tag> ...
tmsu delete landscape
## タグのリネーム:  tmsu rename <old> <new>
tmsu rename mountain mountains

sxiv のステータスにTMSUタグを表示する

まず、 TMSU のタグがステータスに表示されるよう、image-info を以下のように調整する。

#!/bin/bash
# ~/.config/sxiv/exec/image-info

s="  " # field separator

exec 2>/dev/null

filename=$(basename -- "$1")
filesize=$(du -Hh -- "$1" | cut -f 1)
geometry="${2}x${3}"
tmsu_tags=$(tmsu tags -1 "$1" | sed -e '1d' -e 's/\(^.*$\)/\[\1\]/')

echo "${filesize}${s}${geometry}${tmsu_tags:+$s}${tmsu_tags}${s}${filename}"

タグを [ ] で括って表示するようにしてみた。

sxiv_image_viewer_image-info.jpg

sxiv から TMSU タグをつける

キーハンドラに以下のスクリプトを書いて、 C-x t でタグづけ、 C-x T でタグ削除できるようにする。ともにサムネールモードではマーク機能を使って複数ファイルに対して行える。

#!/bin/bash
# ~/.config/sxiv/exec/key-handler

readonly KEY="$1";
readonly TMPFILE="/tmp/sxiv.$$"

tmsu_add_tag() {
  if tag="$(tmsu tags | dmenu -i -p "add tag>")"; then
    tr '\n' '\0' | xargs -0 tmsu tag --tags "\"$tag\""
  fi
}

tmsu_remove_tag() {
  cat >"$TMPFILE"
  if tag="$(tr '\n' '\0' <"$TMPFILE" | xargs -0 tmsu tags -1 | sed -e '/:$/d' -e '/^$/d' | sort | uniq | dmenu -i -p "rm tag>")"; then
    tr '\n' '\0' <"$TMPFILE" | xargs -0 tmsu untag --tags "\"$tag\""
  fi
}

case "$KEY" in
  "t") tmsu_add_tag ;;
  "T") tmsu_remove_tag ;;
esac

上記は前述のサンプル sxiv/key-handler (GitHub) を参考にしている。

既に壁紙のところで記したが、キーハンドラはプリフィクスに続くキーコンボを $1 で受け取り、標準入力にて改行区切りのファイルリストを受け取る。このような場合、受け取るリストは while read でまわしながら読めばトラブルが少ないと考えるが、ここでは xargs で同じ様な効果を得ている。特にヌル文字区切りで渡すところがポイントで、スペースを含むファイル名をうまく扱うためである。

xargs はデフォルトで \s を区切り文字とみなすが、正規表現の \s はいわゆる空白文字であり、スペースやタブ、改行などといったものを示す。だからファイル名にスペースが含まれていればそれも区切りとして捉えてしまう。そこであらかじめ区切り文字をヌル文字だけにしてから xargs に渡すのである。上記スクリプトを例に採れば、 tr で改行を '\0' にして xargs -0 で受け取るとスペースが含まれるファイル名も正常に受け取れるということだ。ちなみに find コマンドでは -print0 オプションでヌル文字区切りの結果を出力してくれる。