Skip to content

Instantly share code, notes, and snippets.

@krtx
Created November 27, 2016 02:48
Show Gist options
  • Save krtx/533d33d6cc49ecbbb8fab0ae871059ec to your computer and use it in GitHub Desktop.
Save krtx/533d33d6cc49ecbbb8fab0ae871059ec to your computer and use it in GitHub Desktop.
fix imgcat to be able to display images on tmux https://gitlab.com/gnachman/iterm2/issues/3898#note_14097715
#!/bin/bash
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
# only accepts ESC backslash for ST.
function print_osc() {
if [[ -n $TERM ]] ; then
printf "\033Ptmux;\033\033]"
else
printf "\033]"
fi
}
function print_csi() {
printf "\033["
}
# More of the tmux workaround described above.
function print_st() {
if [[ -n $TERM ]] ; then
printf "\a\033\\"
else
printf "\a"
fi
}
# Return the height of the image, or 200 if imagemagick is unavailable.
function get_height() {
identify -format "%h" - 2>/dev/null || echo 200
}
# print_image filename inline base64contents print_filename
# filename: Filename to convey to client
# inline: 0 or 1
# base64contents: Base64-encoded contents
# print_filename: If non-empty, print the filename
# before outputting the image
function print_image() {
VERSION=$(base64 --version 2>&1)
if [[ "$VERSION" =~ fourmilab ]]; then
BASE64ARG=-d
elif [[ "$VERSION" =~ GNU ]]; then
BASE64ARG=-di
else
BASE64ARG=-D
fi
local -i HEIGHT=$(printf "%s" "$3" | base64 $BASE64ARG | get_height)
HEIGHT=$(( (HEIGHT + 19) / 20 ))
for (( I = 0; I < $HEIGHT; I++ )); do
printf "\n"
done
print_csi
printf "?25l"
print_csi
printf "${HEIGHT}F"
print_osc
printf '1337;File='
if [[ -n "$1" ]]; then
printf 'name='`printf "%s" "$1" | base64`";"
fi
printf "%s" "$3" | base64 $BASE64ARG | wc -c | awk '{printf "size=%d",$1}'
printf ";inline=$2"
printf ";height=$HEIGHT"
printf ":"
printf "%s" "$3"
print_st
printf '\n'
if [[ -n "$4" ]]; then
echo $1
fi
print_csi
printf "${HEIGHT}E"
print_csi
printf "?25h"
}
function error() {
echo "ERROR: $*" 1>&2
}
function show_help() {
echo "Usage: imgcat [-p] filename ..." 1>& 2
echo " or: cat filename | imgcat" 1>& 2
}
## Main
if [ -t 0 ]; then
has_stdin=f
else
has_stdin=t
fi
# Show help if no arguments and no stdin.
if [ $has_stdin = f -a $# -eq 0 ]; then
show_help
exit
fi
# Look for command line flags.
while [ $# -gt 0 ]; do
case "$1" in
-h|--h|--help)
show_help
exit
;;
-p|--p|--print)
print_filename=1
;;
-*)
error "Unknown option flag: $1"
show_help
exit 1
;;
*)
if [ -r "$1" ] ; then
has_stdin=f
print_image "$1" 1 "$(base64 < "$1")" "$print_filename"
else
error "imgcat: $1: No such file or directory"
exit 2
fi
;;
esac
shift
done
# Read and print stdin
if [ $has_stdin = t ]; then
print_image "" 1 "$(cat | base64)" ""
fi
exit 0
@jamesdbowman
Copy link

This is great! Thanks!

@heliomass
Copy link

Very nice!

@fredcallaway
Copy link

Doesn't work for me with tmux 3.1b, Mac OS 10.15 😕 (I just get a blank area about the size of the image)

@hex0cter
Copy link

Same for me. :-(

@thlorenz
Copy link

Works for me ... images show up at least for a while. If I navigate away or do anything else that (I assume) causes tmux to refresh the pane I get an empty square as well. But for my use case this works. Thanks!

@arifvn
Copy link

arifvn commented Jan 19, 2022

@thlorenz what tmux version did you using?

@rodhash
Copy link

rodhash commented Apr 26, 2025

With updated versions of FzF / Tmux / iTerm this works.

Well, on images up to to 2048x1277 (or something like this) this is working fine but when the image is too much above that then it simply shows a black "img".

Was wondering some way to "resize" images before invoking this, the original imcat has some flags for width/height but they don't work here:

 $  imgcat -h
Usage:
        /opt/homebrew/bin/imgcat [--width=<columns> --height=<rows>|--no-resize] [--no-preserve-aspect-ratio]
                                 [--half-height] [--depth=(8|256|24bit|iterm2)] IMAGE
        /opt/homebrew/bin/imgcat --version
        /opt/homebrew/bin/imgcat --help

Awesome script btw.. a little bit more this possibly could be used with fzf preview too which would be really nice.

@rodhash
Copy link

rodhash commented Apr 26, 2025

Yeah most likely that's why I get those black "imgs", looking into fzf-preview.sh code it uses those Width/Height flags to resize the img.

ie: outside of tmux
image

Now in tmux (here I'm not even using FzF but just previewing the img)

 $  file wallhaven-yxmrxk.jpg
wallhaven-yxmrxk.jpg: JPEG image data, Exif standard: [TIFF image data, little-endian, direntries=6, orientation=upper-left, xresolution=86, yresolution=94, resolutionunit=2], baseline, precision 8, 3840x2400, components 3
image

I'm trying to leverage something from ImageMagick here. This quick test worked successfully (inside tmux).

image

I could wrapper both in a script however it's losing img quality which doesn't seem to happen w/ original imagecat even when inside a FzF preview, no idea how they are shrinking img keeping a good img quality. Anyway, this quick and dirty script worked in tmux:

#!/bin/bash

# Input image file
input_image="$1"

# Resize the image using 'convert' and pipe it to the main script
convert "$input_image" -resize "800x600>" jpg:- 2> /dev/null| imgcat
image

Anyway, just sharing what I did in case it’s useful—this helped me deal with oversized images, though it came at the cost of some quality

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment