Add inline images for foot terminal
Opencljoly wants to merge 8 commits from
Reference in New Issue
There is no content yet.
Delete Branch 'cljoly/mdcat:foot-support'
Deleting a branch is permanent. It CANNOT be undone. Continue?
Foot supports printing images in the terminal. This however relies
on the image being converted to sixels, which are then sent to foot.
This is a proof of concept to convert images referenced in markdown
documents, by calling the external chafa command. Chafa does three
current terminal window. Ideally, we would display the original size
of the underlying image, but that seems difficult over the sixel
medium, because the tool creating the sixel (chafa in our case, but
see below for alternatives) does not know the size of one pixel in
the terminal emulator.
With the Kitty protocol, we don’t have to worry about (1), (2) and (3),
because the terminal emulator is in charge of actually displaying the
To move past the proof of concept phase, we could use a library to get
sixels from an image. chafa is also offered as a C library, but it’s
probably easier to stick to a Rust one, like viuer. That means
however that we have to deal with (1) and (2) ourselves. In particular,
missing remote images might be replaced by an empty image, which could
be stored as some constant sixel code in a variable, a bit like what is
currently done for wezterm.
Another option is to keep using the chafa command line. If it is
available in the path, then we expose the
TerminalCapabilities. This could even improve support of other
terminal emulators, as chafa would detect the capabilities of the
emulator itself, falling back to crafty Unicode to approximate the image
on a terminal emulator that would support neither the kitty protocol nor
What are your thoughts on these two options @flausch?
I'm not sure; I think I'd like to pass this one.
I don't think I'd like to depend on an external tool or library here; we already support the iTerm and Kitty protocols, and the less dependencies the better.
If foot supports only sixel images and has no plans to support any of the other protocols, then at most I think I'd accept a library for RGB to sixel conversion. But printing and formatting for the terminal doesn't seem to be so hard as to warrant a library.
I'm not sure what you're referring to here: mdcat doesn't display empty images if remote images fail; instead it just leaves the original image link in place.
I believe there is no plan1 for foot to support any other protocol. I'll look into using the sixel crate to limit external dependencies then.
I'm not in the foot team, it’s mostly based on this comment. ↩︎
As far as I understand this ocmment foot does not consider image support a priority, so I think mdcat won't consider image support in foot that important either.
I guess if you'd like good image support the idea is too use a different terminal emulator. Wezterm or kitty come to my mind.
So I think I'd only like to add sixel support if the code uses minimal dependencies and doesn't rely on external tools.
Displaying previews of PDF documents as images is very much out of scope for mdcat 🙂
Agreed, it was just an example of how far chafa went :)
Understood, the sixel crate might be suitable then.
f531dabb8711 months ago
c05aefe52d11 months ago
Thanks. As far as I can see it still uses the external command, though.
Did you have a chance to look at this crate you mentioned?
By the way, it looks as if some code changed formatting; did you run rustfmt?
Also the copyright headers don't fit the license. You're free to submit your contribution under the Apache license of ocurse but please be aware that mdcat itself is distributed under the MPL license.
And finally please run scripts/check to see if your change passes all required tests and checks.
I’m looking into it, I have not finished writing the code yet. Not sure I’ll finish today, might have to wait till next weekend.
If that works better for you, I can @ you and request a review when it’s done and rustfmt'd?
Sorry I messed up the headers. I’ll fix this and use the same as what is used elsewhere in mdcat, much easier for everyone.
Yes, just ping me again when this is ready, that'd be nice 🙏
bfc4d2cec811 months ago
(not in a fully working state yet, see the TODO comment)
So it works ok on some images. For instance, the README:
but with other ones (like the sample.md file), not that well:
I think libsixel does not work well with transparent PNG. Perhaps that’s something we can live with, as I have not found another easily accessible sixel lib in rust…
Anyway, this is not ready for review yet.
e417ecc56a10 months ago
57377df53410 months ago
827bb74bb110 months ago
@flausch I have
libsixelcrate uses some very old crates with security issues.
I’ll look further into updating the dependencies of the
libsixelcrate, but you are still happy with adding the
libsixel(C library) system dependancy, right?
I am not sure; I wasn't aware that you were adding a C dependency. You never mentioned that and I understood this
as to say that sixel was a pure Rust implementation. Though you never mentioned that either, so I've really misunderstood something.
I'm sorry to say that I'm not really in favour of adding a C dependency to support an inferior image format for a niche terminal.
mdcatalready supports the two major image formats (namely iterm and kitty), and ideally foot would just support one of these.
If there's no other way I'm okay w/ sixel, but it needs to have up-to-date transitive dependency, and the code must be feature-guarded in mdcat, and the feature off by default, to ensure that mdcat builds clean even if the library is not present or no C compiler installed.
I’m sorry I did not make it clear there would be this new C dependancy. I probably figured it out along the way, initially I thought it would be a nice pure Rust dependancy.
Reading this PR again, you also made it clear that you would prefer no external C dependancies early on. I might have lost sight of that when I worked on the sixel crate integration. So really, I should not have asked “but you are still happy with adding the libsixel (C library) system dependancy, right?”.
That makes total sense!
Now, on the one hand, if we are feature-guarding the sixel support in mdcat, a user of a terminal that would support sixel would need a custom build of mdcat. That would also likely not be supported by the package manager of their GNU/Linux distribution.
On the other hand, with a clean integration of an external command like
chafa(cleaner than my initial prototype), we could dynamically enable sixel support for foot users. If the user does not have chafa installed, we fallback to the default support (just a link to the image). If the user does have chafa in the $PATH, then mdcat detects it and uses chafa to print the image as sixel. This also means that the user can use an out of the box distribution package and just install the external
chafadependancy for sixel support.
This used of an external command would be similar to what is done with
rsvg-convert, for the image support of iterm2.
Based on your experience maintaining the
rsvg-convert code, do you think introducing something similar with
chafawould be an option, instead of pursuing the path of a feature-guarded libsixel integration?
I'm not sure. SVG support is no role model here.
SVG is a terribly complex format, and requires a whole 2D rendering pipeline to turn into pixel graphics, and back then this meant rsvg, Cairo, SVGKit and a hell lot of other native C dependencies. These days I'd just go with resvg and call it a day, even if SVG coverage is perhaps incomplete compared to rsvg.
Getting rid of rsvg-convert is definitely a goal.
So, if there's really no other way to get images on foot, then I'll grudgingly accept an external command, but I definitely don't like it, and I'd really prefer if we had some other means. After all, Sixel isn't SVG, it doesn't need a rendering pipeline, it just turns pixels into a bunch of ASCII characters. How hard can that be?
Coming back I realized that my last comment was very negative, which wasn't really my intention.
Please do update this merge request so that it uses an external command for sixel conversion, in absence of any good Rust implementation. I'll review it again and merge it 🙂
I'm just a tad disappointed that there's no pure Rust implementation, and that foot doesn't support a more powerful image format 🙈
It’s ok, the situation is quite frustrating: no native Rust library, bindings only to libsixel which requires an intermediary file and to separately install a library.
That prompted me to look more into the sixel format and to start a pure Rust library (it's still in very early stage though).
The last commit I pushed was just using a crate with up to date dependencies for libsixel. I’ve just seen your message, so probably next week I'll integrate