View images over a tmux pane in the TTY

Introduction

I have found a little solution to play videos over tmux panes in the TTY. Now I wanted to achieve the same with viewing images. I could not find any framebuffer image viewer that allows me to specify both the positioning and size of images with command line arguments. Therefor, I turned to my old friend mplayer which gives me all of these options and checked out if I could turn it into something it's not meant to be.

Solution

Here is what I came up with:


#!/bin/zsh

clear

font_width=8
font_height=16

pane_cols=$(tput cols)
pane_rows=$(tput lines)

pane_width=$(($pane_cols*$font_width))
pane_height=$(($pane_rows*$font_height))

pane_top=$(tmux list-panes -F "#{pane_top}" -f "#{pane_active}")
pane_left=$(tmux list-panes -F "#{pane_left}" -f "#{pane_active}")

pane_y=$(($pane_top*$font_height))
pane_x=$(($pane_left*$font_width))

image_width=$(exiftool -b -ImageWidth $1)
image_height=$(exiftool -b -ImageHeight $1)

pane_ratio=$(bc -l <<< "$pane_width / $pane_height")
image_ratio=$(bc -l <<< "$image_width / $image_height")

if [[ $image_ratio -gt $pane_ratio ]]; then
        width=$pane_width
        height=$(bc <<< "$width/$image_ratio")
        height_diff=$(($pane_height-$height))
        x=$pane_x
        y=$(($pane_y+$(($height_diff/2))))
else
        height=$pane_height
        width=$(echo "$height*$image_ratio" | bc -l | sed 's/\..*$//')
        width_diff=$(($pane_width-$width))
        y=$pane_y
        x=$(($pane_x+$(($width_diff/2))))
fi

extension=$(echo $1 | sed 's/.*\.//')

mplayer "mf://$1" -mf type=$extension -loop 0 \
        -vo fbdev2 -zoom -x $width -y $height -fps 1 \
        -geometry $x:$y > /dev/null 2>&1  
			

As you can tell, I mostly recycled the script from my tmux-friendly mplayer script. I still get tmux pane geometry information and info about the image aspect ratio and this is used to calculate everything that mplayer needs to position the media accordingly.

I added the -mf option that allows me to display image media formats, I also added the -loop option that plays the image in an infinite loop. This however really burned through my ressources, so I lowered the framerate to 1 FPS with -fps.

To run this script you need to have zsh, exiftool, bc and of course mplayer and tmux installed.

Shortcomings

Again, resizing the tmux pane will not resize the image. You would need to close mplayer and rerun the script. Also, this is not an image gallery where you can skip through multiple files. It just opens one file at a time.