ihabunek / toot

toot - Mastodon CLI & TUI
GNU General Public License v3.0
1.16k stars 111 forks source link

Any interest in a built-in image viewer? #243

Open danschwarz opened 1 year ago

danschwarz commented 1 year ago

I've been working on a new urwid widget that leverages chafa or imgcat (external apps) to render images in an overlay window in character mode - 16 color, 256 color, or truecolor. Progress so far:

Screenshot 2022-11-30 180423

Single-image display from a status works as you see here.

Open issues include getting the widget size correct, async loading of images, handling multiple images and navigating between them.

Then I came across another project, term-image, that does a great job of image rendering in urwid - they've created an image list box - it even handles kitty and iTerm graphics modes for pixel-accurate images.

Importantly, it's pure Python code with no external app dependencies. It uses the Pillow library for image processing.

The project mentions future plans to create standalone urwid widgets, but as of now, their GridListBox widget only exists as part of their demo viewer app. Here's their widget code (MIT-licensed).

danschwarz commented 1 year ago

Experiment- inline image viewing

Screenshot 2022-12-10 202152
ghjardim commented 1 year ago

I support this feature. I think image preview (through the user's choice of an external viewer, like w3m-img, chafa, asciiart) can bring a great user experience to this client!

AnonymouX47 commented 1 year ago

Wow! I just kinda stumbled on this. πŸ˜„ I had no idea anyone had been looking into my code (I'm the author of term-image)... πŸ‘€

Yeah, I composed a couple of widgets to display images and I've always had plans to include them in the public API but for two main reasons, I haven't:

  1. I felt the widgets were still quite non-fine-tuned and hacky around the edges (particularly the GridListBox you mentioned).
  2. Until now, I had not seen any demand for the widgets.

I'm currently working on separating the library from the CLI/TUI (I.e separate projects, for various reasons) and I'm almost done with that, then I'll make a release. I should be able to include the widgets in the next release after that.

Anyways, @danschwarz it would've been really helpful if you opened an issue requesting for the widgets instead of what your suggestion up here insinuates. πŸ˜ƒ

Thanks ❀️

danschwarz commented 1 year ago

@AnonymouX47 your code is incredible and was the inspiration for the ASCII and Sixel image updates that I've been doing for this project. I'm still learning a lot from it! I refrained from opening an issue because your readme noted you were taking time to focus on your studies. No offense meant. I can open one now if that'd be helpful.

AnonymouX47 commented 1 year ago

Oh!... the studies. πŸ€¦πŸΎβ€β™‚οΈ I've actually been done with that for a while now and I'm back in development of the project.

No offense meant. I can open one now if that'd be helpful.

None taken. Yeah, a feature request as regards that would be good.

Thanks

danschwarz commented 1 year ago

I don't think we could directly use GridListBox in the toot project, but the core code that draws ANSI, Sixel, Kitty, and iTerm2 images within an Urwid canvas may be useful and better than what I've written so far. I've opened up an issue. When it comes to Urwid, I think that "hacky around the edges" is pretty much the best one can hope for, because the core Urwid framework hasn't been updated in years. Perhaps someone will step up, fork it and deal with the outstanding PRs and issues, or perhaps it's time to move on to Rich/Textual...

AnonymouX47 commented 1 year ago

When it comes to Urwid, I think that "hacky around the edges" is pretty much the best one can hope for

Yeah, true.

or perhaps it's time to move on to Rich/Textual...

I've actually been really considering this of recent. Even though the project is still in its early stages, it already has a lot to offer and is way more modern than any other similar project.

hackdefendr commented 1 year ago

My friend created NotCurses https://notcurses.com/ and I bet if you were to re-write toot with it the images displayed would look better, load faster, and would make the TUI sparkle. Should I put in an official feature request?

AnonymouX47 commented 1 year ago

I must say, rewriting will definitely be a whole lot of work.

danschwarz commented 1 year ago

Frankly it’d probably be easier to write a new urwid back end targeting notcurses. There’s already a curses back end and a raw (direct ANSI) back end.

On Sat, Feb 18, 2023 at 10:14 AM HackDefendr @.***> wrote:

My friend created NotCurses https://notcurses.com/ and I bet if you were to re-write toot with it the images displayed would look better, load faster, and would make the TUI sparkle. Should I put in an official feature request?

β€” Reply to this email directly, view it on GitHub https://github.com/ihabunek/toot/issues/243#issuecomment-1435697611, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAY4FJQBZXVRLMBOEUN656DWYDROFANCNFSM6AAAAAASR7NKLQ . You are receiving this because you were mentioned.Message ID: @.***>

hackdefendr commented 1 year ago

Unless I misread the notcurses docs, the library is written to be a drop-in replacement for curses. I am not 100% sure how that all works, but I think it would be worth a urwid back end at least and if the tests warrant it then do a total rewrite later.

AnonymouX47 commented 1 year ago

Unless I misread the notcurses docs, the library is written to be a drop-in replacement for curses.

You probably misread :thinking:. From the project's README:

What it is not: a source-compatible X/Open Curses implementation, nor a replacement for NCURSES on existing systems.

danschwarz commented 1 year ago

So presumably you could drop it in place of ncurses, but leveraging the advanced features- say, building image widgets with pixel rendering using notcurses features- would require additional coding. May be worthwhile to try.

On Sat, Feb 18, 2023 at 2:28 PM Toluwaleke Ogundipe < @.***> wrote:

the library is written to be a drop-in replacement for curses

From the project's README:

What it is not: a source-compatible X/Open Curses implementation, nor a replacement for NCURSES on existing systems.

β€” Reply to this email directly, view it on GitHub https://github.com/ihabunek/toot/issues/243#issuecomment-1435751696, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAY4FJVP7CF3V6CM6P6OQGDWYEPFPANCNFSM6AAAAAASR7NKLQ . You are receiving this because you were mentioned.Message ID: @.***>

hackdefendr commented 1 year ago

I like the idea of trying. Who knows it might just work. I wish I could code better, I would love to at least try and figure out how to do everything first and then submit a PR for people to test. Unfortunately, my coding is minimal so I'm better off testing things out if it moves forward.

ihabunek commented 1 year ago

My friend created NotCurses https://notcurses.com/ and I bet if you were to re-write toot with it the images displayed would look better, load faster, and would make the TUI sparkle. Should I put in an official feature request?

Thanks for the suggestion, but a full rewrite would be a tall ask. I'm late even with fixing bugs and merging Dan's PRs.

I'm not famiiliar with notcurses, but it seems to be a bit more low-level than Urwid. If we were to go for a rewrite, I'd probably aim for something which offers higher-level components for layout, list boxes, styling, focus management and the like. I'm liking textual, although it's still a bit early in development.

hackdefendr commented 1 year ago

In talking to Nick, my friend that created NotCurses, it is not a drop in replacement for Curses, but does use the terminfo bindings from NCurses where ever possible. Does that make sense? He also said NotCurses isn't a total rewrite requirement that you really could essentially drop it in with minimal coding.

I took a look at URWID and NotCurses side by side, and truthfully I don't think it looks better than what NotCurses produces. Dropping his GitHub for one last attempt to persuade someone to at least try it. I'd try it myself, but I'm not a coder, I'm more of a scripter.

https://github.com/dankamongmen/notcurses

danschwarz commented 1 year ago

Notcurses is very impressive, but it's a low level foundation on which you can layer a TUI library like Urwid. It doesn't provide the higher level GUI elements that Urwid does for an app developer.

Simply porting Urwid to run on Notcurses seems possible, perhaps even easy, but without additional work it would give you zero benefit. None of the bling that you see in the Notcurses demo app.

Let's say you ported Urwid to run on Notcurses. Now you have to write a bunch of Urwid widgets to take advantage of the Notcurses functionality, and you have to modify toot to use them. That might be an interesting project for someone to take on. Personally, I don't have the bandwidth to take that on right now.

I have been working with @AnonymouX47 on his UrwidImage widget, which gives us cell-based and pixel-based rendering to support image display in Urwid apps. It's already up and running in a development build of toot on my system. Here's an example of image display using the Kitty terminal app.

image

AnonymouX47 commented 1 year ago

@hackdefendr, I actually saw your comment almost immediately after it was posted but wasn't sure what else to say. I'll try my best to give the facts on this matter.

NotCurses is undoubtedly a great and advanced library for building TUIs. The author (dankamongmen) is someone I've always respected for his work, not only on NotCurses but also across various other projects and discussions within the community of TE and TUI app developers. Trust me, no one could be involved in this community for a while and not see his name and work all over.

That said, I should explain why what you're suggesting is a non-trival task.

The first and major obstacle is that the python bindings for NotCurses seem to be largely incomplete and completely undocumented, which actually shocked me when I found out. You can install the package from PyPI and check it out yourself, using it is like "Goodluck figuring it out!". Of course, the C headers are quite documented but IMO that is not always directly useful or sufficient for the python bindings. For example, see Python's stdlib curses module and how well documented it is.

The only way I can see it being usable in a python project is by writing your own bindings, which also is not trivial. This makes it very difficult for developing a NotCurses backend for urwid or porting toot (or any other python project) to use NotCurses.


I took a look at URWID and NotCurses side by side, and truthfully I don't think it looks better than what NotCurses produces.

The main difference is in what they provide, not produce. As far as I know, urwid provides way more high-level components for developing TUIs and even with that, developers still have to write custom widgets for almost any substantial TUI app.

Dropping his GitHub for one last attempt to persuade someone to at least try it. I'd try it myself, but I'm not a coder, I'm more of a scripter.

πŸ‘€


Thanks πŸ™‡πŸΎβ€β™‚οΈ

AnonymouX47 commented 1 year ago

I checked again and noticed there is another set of python bindings here which seems to be well documented but i can't seem to find any means of installation other than the source code and that is not something one can use as a dependency.

@hackdefendr If you have any info about this, please let me know.

Thanks.

AnonymouX47 commented 1 year ago

Did a little digging and it appears the issue is, the project author (dankamongmen) has stopped active development of the project (see https://github.com/dankamongmen/notcurses/issues/2624#issuecomment-1286236881; didn't know this until now). Same goes for the author of the new bindings (igo95862). Even the new bindings are incomplete as of now.

See https://github.com/dankamongmen/notcurses/issues/1154, https://github.com/dankamongmen/notcurses/issues/2624 and https://github.com/dankamongmen/notcurses/issues/2670.

So, I guess what I said still holds. To use NotCurses in a python project, one would need to write python bindings or use some other means of using C code in python.

hackdefendr commented 1 year ago

Ok I will drop it as it seems there is a better way.

ploum commented 4 months ago

It would be awesome to have image preview through chafa.

AnonymouX47 commented 4 months ago

@ploum, image preview has actually been implemented.

Install toot with

pip install "toot[images]"

and then see the -f | --image-format option of toot tui (I believe there's also a corresponding config option).


@ihabunek @danschwarz

I had in mind to mention this a while back but it has since skipped my mind.

I noticed that both image and rich text support aren't advertised in any way. Currently, only a user who for some reason looks into pyproject.toml would be aware of these features and how to enable them since they require optional dependencies.

I would suggest that, at least image support, be included in the list of features in the README.

Also, It'll be good to describe installation of extra features, then list and describe available extras in the installation page of the docs.

Finally, I think all image support issues can be closed now.


Thank you all. :smiley:

ploum commented 4 months ago

I concur to this. I’m using the Debian package and I’m not sure that the maintainer is aware of this (as it is disabled on the package)

danschwarz commented 4 months ago

I can update the readme. I think the screenshots also should be updated and I can provide new ones, with image examples.

danschwarz commented 4 months ago

PR #491 addresses @AnonymouX47 's issue above (at least minimally.) More can be done, but it's a start.