Refactor popup image feature by 64-bitman · Pull Request #21234 · vim/vim · GitHub
Skip to content

Refactor popup image feature - #21234

Draft
64-bitman wants to merge 76 commits into
vim:masterfrom
64-bitman:image_refactor
Draft

64-bitman wants to merge 76 commits into
vim:masterfrom
64-bitman:image_refactor

Conversation

@64-bitman

@64-bitman 64-bitman commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Refactor the popup image feature to fix various issues. I've separated the image logic from the popup window logic, which is more maintainable in my opinion. This should also allow for other possible uses of images (graphical icons in the statusbar?)

  • I plan on this to be fully backwards compatible, except now instead of automatically detecting the image protocol to use (for terminal), to use imageprotocol option instead (yet to be implemented), similar to keyprotocol.

  • Additionally, images can be added with the image_add() function (to be implemented), which can then be used by multiple popup windows/sources. Images are separated from their placements (visible sources of the image), which decreases memory usage when needing to use the same image multiple times.

  • I plan on adding tests in this PR, TODO how

  • Sixel (terminal)

  • GDI (MS-Windows GUI)

  • Cairo (GTK2/3)

  • GDK (GTK4)

  • Kitty (terminal)

Other unrelated bugs I've noticed:

  • clipwindow does not seem to work correctly with nowrap in general

@64-bitman
64-bitman force-pushed the image_refactor branch 4 times, most recently from 6901e89 to 534391c Compare September 6, 2026 02:36
Comment thread src/image.c Fixed
Comment thread src/image.c Fixed
@Yamagi

Yamagi commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

@64-bitman

Copy link
Copy Markdown
Contributor Author

I plan on this to be fully backwards compatible, except now instead of automatically detecting the image protocol to use (for terminal), to use imageprotocol option instead (yet to be implemented), similar to keyprotocol.

A suggestion for improvement:

The SIXEL protocol is the most inferior protocol supported by Vim right now since it's limited to 255 colors. For good results any non trivial image must be properly quantized to 255 colors. While it would be nice to have quantization in Vim, I understand that quantization is a non-trivial problem and not in the scope of the project. After all Vim isn't an image viewer.

I've experimented with quantization through pngquant (properly the best quantization implementation out there) and was able to yield good results.

This image is just 'resize by ImageMagick -> convert to RGBA -> display by Vim'. You can see the artifacts caused by missing quantization:

Bildschirmfoto_20260906_124756 This one was rendered by 'resize by ImageMagick -> quantize with `pngquant -o $OUTPUT --posterize 2 255` -> convert to RGBA -> display by Vim'. The quality is drastically better: quant Source code of my highly experimental plugin implementing this can be found here: https://codeberg.org/yamagi/vim-imagepopup

Long story short: It would be very appreciated if Vim provided a way to detect the color depth supported by the active image backend. Or at least what image backend is active. That way a plugin could determine automatically how the image should be processed before it's displayed by Vim.

I suppose there can be a v: variable for this. However I'm not sure how you would detect the color depth from the image backend? Shouldn't this be possible by just knowing what image backend is being used?

@Yamagi

Yamagi commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

I suppose there can be a v: variable for this. However I'm not sure how you would detect the color depth from the image backend? Shouldn't this be possible by just knowing what image backend is being used?

Good point. Thinking about it the only real advantage of a colordepth variable would be the addition of new backends existing plugins don't know about. But I would suspect that any new backend, be it in GUI or some new terminal protocol, would likely support 24 bit colors. So knowing what backend is used would be enough for plugin authors to special case SIXELs.

@dezza

dezza commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

I like both of your ideas of a more generic image_add and embedding images inside documents.

I'd suggest keep the idea/impl open to the idea of animated images and fixing to lines with the tallest image setting the lineheight.

Animated images/shaders inside a markdown document templeOS style;
image

I have conceal on all my markdown formatting and animated images unconcealing to file-refs on cursor over would look so cool, especially if blog writing from within vim.

@64-bitman

Copy link
Copy Markdown
Contributor Author

I've decided to switch to using the libsixel library for the sixel support. Sixel is honestly really complex and has a bunch of edge cases that does not seem right for a text editor to have to implement. Additionally libsixel seems to be very well known and well distributed, and supported on all relevant platforms. This makes maintainance in the future easier

@64-bitman
64-bitman force-pushed the image_refactor branch 6 times, most recently from 73df265 to 79572c1 Compare September 7, 2026 05:03
@64-bitman

64-bitman commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

I'm going to put off creating the tests in this PR. I've thought of several solutions, but I think the most suitable one would to literally implement sixel in the builtin terminal (libvterm). Then there could be a term_dumpwrite() like function that can dump a pixel buffer view of the terminal, which can be compared. This should be maybe feasible? (with the help of the Cairo library and maybe Pango to render text? (probably unecessary for testing)). This is a nice feature in its own right as well.

The initial sixel support can be very rudimentary, possibly without scrollback support or sixel scrolling (DECSDM).

This all sounds a bit overkill for just a test suite, but it looks like a fun challenge for me 😄

@64-bitman
64-bitman force-pushed the image_refactor branch 2 times, most recently from a6a50c5 to fb74b04 Compare September 9, 2026 03:20
@64-bitman

Copy link
Copy Markdown
Contributor Author

I have done a big refactor, now pixman is a dependency for the image feature. This is because I need to handle having some parts of the image being under some text (e.g. border). For sixel this is simply a matter of ordering how you draw everything to the screen. However for the kitty graphics protocol and GTK4, images are actual "objects", not just pixels blit to the screen, meaning there has to be a way to figure out what rectangles in an image are visible. Pixman does that, its very fast (SIMD optimized) and well tested, and has no dependencies. Additionally pixman has some image manipulation features that can we possibly expose to the user (e.g. cropping, scaling).

Before:

recording_2026-09-08_23-14-49.mp4

After:

recording_2026-09-08_23-15-23.mp4

@64-bitman
64-bitman force-pushed the image_refactor branch 7 times, most recently from fb5acb6 to 43d0efc Compare September 11, 2026 02:50
@64-bitman

Copy link
Copy Markdown
Contributor Author

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants