image.nvim
image.nvim copied to clipboard
Is sixel is in Consideration?
As I remember earlier sixel was mentioned in README for future but now I guess it is removed.?
I think you are talking about this plugin: https://github.com/samodostal/image.nvim
Which actually has the same name but developed completely separately. And in the world of lazy.nvim, I'm not sure if it is possible to install both due to name collision.
I think you are talking about this plugin: samodostal/image.nvim
Which actually has the same name developed completely separately. And in the world of
lazy.nvim, I'm not sure if it is possible to install both due to name collision.
nop, i guess i do remember it was for this one.
here check this commit https://github.com/3rd/image.nvim/blob/e82623458a08d9f43a67ef84e34dacf5c19f007b/README.md it contains sixel
Oh, sorry :sweat_smile:
Hey, the answer is yesss! Didn't get to it yet, but it's definitely comming.
There's already something like this, I need to reach out to @bytesnake as they've done a lot of work on this already.
It's a funny story, I made the vimage experiment as well, a few years ago #nevergiveup :joy:
https://www.reddit.com/r/vim/s/L5llxvrl9s
Sixel support will be amazing
Considering Sixel support would be beneficial as it opens compatibility with multiple terminal emulators beyond Kitty, such as iTerm2, Alacritty, wezterm, and others. I primarily use iTerm2, so I was contemplating the iTerm Image Protocol, but if Sixel support is achieved, it seems like a comprehensive solution.
+1, kitty protocol only works on kitty. Sixel is the industry standard.
Sixel support landed in tmux master recently. I concur that would be the bees knees.
@stephenprater this is amazing news!
Have been using it for a long time and it is stable. Also used it with fzf as it now also got sixel.
Any news on this? I have FOOT terminal and LF with other parts of my GNU/Linux system all with sway/Wayland and Sixel only piece missing is Neovim with sixel.
Any news on this? I have FOOT terminal and LF with other parts of my GNU/Linux system all with sway/Wayland and Sixel only piece missing is Neovim with sixel.
I'm in the same boat. Sixel is the way to go here where more terminal emulators support it than any other protocol that I know of. Now that tmux supports it and it also propagates over ssh, I think it would provide the most cohesive experience for remote development workflows.
This does the job (credit to the original author - my fork fixes building on more up-to-date toolchains), but it is quite taxing on system resources.
There's a new lua plugin to bring sixel to neovim: sixelview.nvim.
I'm the author of neither of these plugins but I hope someone can step up to migrate this plugin into image.nvim/image/backends.
I had a go at merging the functions in sixelview.nvim into a something that resembles what is done for the ueberzug here [1]. There are quite a bit of issues:
- ~~Image has a very large chance (>80%) of not rendering in full. This was also an issue in sixelview, so there might be additional parsing we need to do to the sixel string before we can run the renderer. (I'm also no sure why the display is inconsistent)~~ (Edit: fixed in latest commit)
- I'm not sure how to have a performance way of clearing sixel image in neovim. The only way I know of is to run
:mode. (Edit I'ved tried to create a dummy sixel image on the fly, but that breaks the rendering completely.)
If someone is more knowledgeable in how to process sixel output, let me know what I might proceed.
[1] https://github.com/yimuchen/image.nvim/blob/sixel_support/lua/image/backends/sixel.lua
Perhaps this contribution can shed light on implementing sixel in this plugin. I recently developed a preview that supports sixel for fzf-tab, I leave the code here. The function is called draw and it works perfectly.
#!/usr/bin/env sh
CELL_HEIGHT=22
CELL_WIDTH=12
HEIGHT=$(($FZF_PREVIEW_LINES * $CELL_HEIGHT))
MAX_WIDTH=$(($FZF_PREVIEW_COLUMNS * $CELL_WIDTH))
TMP="/tmp/fzf-preview"
LTMP="$HOME/.cache/fzf-preview"
CACHEFILE="$TMP/$(echo "$1" | base64).png"
LCACHEFILE="$LTMP/$(echo "$1" | base64).png"
maketemp() {
[ ! -d "$TMP" ] && mkdir -p "$TMP"
[ ! -d "$LTMP" ] && mkdir -p "$LTMP"
}
previewclear() {
printf '\033[2J\033[H' # Clear screen
}
text() {
bat --pager=never --wrap never --style="changes" --color="always" "$1" -p
}
archive() {
local filename="$1"
local extension="${filename##*.}"
# Determine the tool to use based on the file extension
case "$extension" in
zip)
unzip -l "$filename" | awk 'NR>3 {print $4}'
;;
tar | tgz | tar.gz)
tar -tf "$filename"
;;
tar.bz2 | tbz2)
tar -tjf "$filename"
;;
tar.xz | txz)
tar -tJf "$filename"
;;
rar)
unrar l "$filename" | awk '/^[ ]+[0-9]/ {print $NF}'
;;
7z)
7z l "$filename" | awk 'NR>18 {print $NF}'
;;
*)
echo "Unsupported file type: $extension"
;;
esac
}
draw() {
dimensions=$(identify -format "%wx%h" "$1")
original_width=$(echo $dimensions | cut -d'x' -f1)
original_height=$(echo $dimensions | cut -d'x' -f2)
aspect_ratio=$(echo "scale=4; $original_width / $original_height" | bc)
WIDTH=$(echo "scale=0; $HEIGHT * $aspect_ratio / 1" | bc)
if [ "$WIDTH" -gt "$MAX_WIDTH" ]; then
WIDTH=$MAX_WIDTH
HEIGHT=$(echo "scale=0; $WIDTH / $aspect_ratio / 1" | bc)
fi
img2sixel -w "$WIDTH" -h "$HEIGHT" "$1"
}
image() {
draw "$1"
}
# https://ffmpeg.org/ffmpeg-filters.html#showspectrum-1
audio() {
[ ! -f "$CACHEFILE" ] && ffmpeg -loglevel 0 -y -i "$1" -lavfi "showspectrumpic=s=hd480:legend=0:gain=5:color=intensity" "$CACHEFILE"
draw "$CACHEFILE"
}
video() {
[ ! -f "$LCACHEFILE" ] && ffmpegthumbnailer -i "$1" -o "$LCACHEFILE" -s 1024 -q 10 &>/dev/null
draw "$LCACHEFILE"
}
pdf() {
[ ! -f "$CACHEFILE.png" ] && pdftoppm -png -singlefile "$1" "$CACHEFILE" -scale-to 1024
draw "$CACHEFILE.png"
}
epub() {
[ ! -f "$CACHEFILE" ] && epub-thumbnailer "$1" "$CACHEFILE" 1024
draw "$CACHEFILE"
}
main() {
previewclear
maketemp
mimetype=$(file -b --mime-type "$1")
case $mimetype in
application/epub*)
epub "$1"
;;
application/pdf)
pdf "$1"
;;
application/zip | application/x-tar | *rar | application/gzip)
archive "$1"
;;
audio/*)
audio "$1"
;;
image/*)
image "$1"
;;
text/*)
text "$1"
;;
video/*)
video "$1"
;;
inode/directory)
[ "${1##*/..*}" = "" ] && echo || eza --icons --color=always --tree --level=2 --git "$1"
;;
*)
text "$1"
;;
esac
}
main "$1"
Would love Sixel support. I've taken a crack at it in my own plugin (virt_lines is the most recent branch), but I feel like I've had to do a lot of dirty things to get it to work nicely, namely:
- I use Konsole+tmux, which isn't as kind as I'd like it to be for Sixels. Screen refreshes use
:modeand, if $TMUX is set, detach and immediately reattach the session. This is the cleanest workaround I know of, but causes flashing on lower-end machines. - Some applications (looking at you, pexpect) don't like forwarding dimensions available via TIOCGWINSZ to their child pseudoterminals. I came up with a
pstreehack to try retrieving them from parent tty devices which seems to do the trick, though. - Trying to support Neovim 0.7 as well as 0.10 ~~because my work laptop still runs Ubuntu 22.04~~. The worst polyfill I've had to do here involves disabling
virt_lines-style extmarks, since placing that correctly involves going throughnvim_win_text_height. - Fold keybinds (zf, zo) are rebound to also redraw Sixel extmarks, if necessary.
- Adding a new
virt_linesextmark outside of the plugin misaligns things, though.
- Adding a new
I also never looked into how to slice Sixels more cleanly, which would be better than completely rerendering with ImageMagick (like I'm doing). At the very least, I'm wrapping magick directly, instead of depending on the Luarock (#124).
I'm in the same boat. Sixel is the way to go here where more terminal emulators support it than any other protocol that I know of. Now that tmux supports it and it also propagates over ssh, I think it would provide the most cohesive experience for remote development workflows.
This does the job (credit to the original author - my fork fixes building on more up-to-date toolchains), but it is quite taxing on system resources.
That was actually the plugin I was working off of (initially in Python, then in straight Lua). I split out the markdown stuff into another plugin, if you're interested (virt_lines is also the most recent branch there).
Thanks a lot for the hints! In the first version I used the pstree workaround as well. Sixels are definitely interesting and I'll work towards that, right now the focus is on finishing the first rewrite which has pluggable renderers and will support direct use of the magick CLI as well (will probably be the default since everyone has issues with the rock), and after I'll build a custom fast renderer to move in the direction of a graphics library as well. In the end I'd like to offload the whole render-and-send-to-term-in-whatever-way part to an external program so that the editor only has to manage editor stuff and offload most logic, only providing a proxy maybe for writing to the tty, if even that is needed. Thanks again, will revisit soon!