-
Notifications
You must be signed in to change notification settings - Fork 888
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kitty image preview #1077
Kitty image preview #1077
Conversation
cd7df82
to
94b7345
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 Great work. I didn't really get into the code changes because it's so much and I'm not familiar with this part of the codebase but there's a couple typos I noticed.
doc/ranger.pod
Outdated
@@ -205,6 +205,11 @@ This feature relies on the dimensions of the terminal's font. By default, a | |||
width of 8 and height of 11 are used. To use other values, set the options | |||
C<iterm2_font_width> and C<iterm2_font_height> to the desired values. | |||
|
|||
=head3 terminology | |||
|
|||
This only works in terminology. It can render vectors graphics, but works only locally. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small typo "vector graphics".
doc/ranger.pod
Outdated
|
||
This only works on Kitty. | ||
It requires PIL or pillow at the moment to work. A nasty bug that can | ||
corrupt the terminal window when scrolling quicly many images, that can |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo "quickly through". "by with" drop one.
ranger/config/rc.conf
Outdated
@@ -85,13 +85,32 @@ set preview_images false | |||
# width of 8 and height of 11 are used. To use other values, set the options | |||
# iterm2_font_width and iterm2_font_height to the desired values. | |||
# | |||
# * terminology: | |||
# Previews images in full color in the terminology terminal emulator. | |||
# Supports a wide variety of formats, even vector graphics like svg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
End the sentence with a '.' : )
ranger/config/rc.conf
Outdated
# | ||
# * kitty: | ||
# Preview images in full color using kitty image protocol | ||
# (https://github.com/kovidgoyal/kitty/blob/master/graphics-protocol.asciidoc), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe move the url to a footnote?
ranger/config/rc.conf
Outdated
# Preview images in full color using kitty image protocol | ||
# (https://github.com/kovidgoyal/kitty/blob/master/graphics-protocol.asciidoc), | ||
# Requires python PIL or pillow library. | ||
# In experimental stage: tmux support is untested, and a scrolling too fast a folder with many images may glitch ranger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a rephrasing. "and scrolling too fast through a folder..."
ranger/config/rc.conf
Outdated
# Future improvements to kitty will ameliorate this issue, for now call the command 'redraw_window' to get rid of the garbage. | ||
# | ||
# * kitty-network | ||
# Similar to base kitty, bit instead of local storage it uses kitty's protocol special feature to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"bit" -> "but"
ranger/config/rc.conf
Outdated
# Similar to base kitty, bit instead of local storage it uses kitty's protocol special feature to | ||
# stream the whole image over standard input. More error prone, and more intensive since it scales down images, | ||
# producing also worse quality previews. | ||
# However it makes possible to see previews froma ranger instance over the network, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"it makes it possible to see previews from ranger over the network" (emphasis for clarity not intended as emphasis)
ranger/container/settings.py
Outdated
@@ -98,7 +98,8 @@ | |||
'confirm_on_delete': ['multiple', 'always', 'never'], | |||
'line_numbers': ['false', 'absolute', 'relative'], | |||
'one_indexed': [False, True], | |||
'preview_images_method': ['w3m', 'iterm2', 'urxvt', 'urxvt-full'], | |||
'preview_images_method': ['w3m', 'iterm2', 'urxvt', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still missing terminology setting?
ranger/core/fm.py
Outdated
elif self.settings.preview_images_method == "kitty": | ||
return KittyImageDisplayer() | ||
elif self.settings.preview_images_method == "kitty-network": | ||
return KittyImageDisplayer(stream=True, resize_height=480) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the height be determined dynamicall?
ranger/ext/img_display.py
Outdated
|
||
|
||
@contextmanager | ||
def temporarly_moved_cursor(to_y, to_x): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo "temporarly".
Oh, wow, those are some embarrassing-grade typos. I even left in notes about the scrolling bug when it has been solved...I should have double checked this stuff. Thanks for the rundown.
*dynamically :P Jokes aside, that's a very bad name when taken out of context. It is not related to the viewbox rectangle, but it is the max tolerated height before the image gets scaled down internally to ease the transfer. I should just base it off the actual area now that I think of it. |
Even though it's technically not referring to the viewport it would seem to me like it's definitely dependent on the viewport. If you're scaling down anyway it doesn't make sense not to scale down all the way to a small viewport. Having a hard cap makes some sense but should imo be based on (10Gb) LAN so not a very hard cap ; ) |
Technically you are half right, but the issue is not only bandwidth, but also the fact that the payload in the APC is base64 encoded. Encoding a filename is easy, encoding a whole big image in RBG(A) is a minute worth of time, at least with the basic python implementation. I thought it would also benefit slow hdds when saving the temporary image when not in network mode. So for now I am going to execute the resize only in the case of |
94b7345
to
bf28ea1
Compare
Thank you for all the work on this. I'm waiting for a couple kitty users to test this. Or some more maintainer eyes on the patch, since it's significant. |
I've been testing this PR for personal use and have noticed the following:
Apart from that, great job, I'm looking forward to being able to see images again :) |
Thanks @tkerber for the tests!
My mistakes, and this actually makes sense. What it doesn't make sense is that I tested and it worked for me before. Probably a typo when calling
I actually had no idea on how to show an error message, I thought that exception were silently ignored, but it turns out that if you have a message attached it gets printed in red to the status bar. I am moving it there in the next commit, possibly adding something like "please search your repositories for the python library pillow" (suggestions welcome).
This is "by design" in a way, but I do agree that it looks kinda of meh. I didn't notice because I was testing with a medium sized terminal in a folder with big images. Anyway, since I was going to implement resizing the thumbnail to the viewport size (with some decent filter) for downsizing, it should made upsampling a bit better too. However I do agree that it might be good to want images sized as close as possible to the native size, so would it make sense to implement a config option to switch between this different behaviors? It could possibly be back-ported to other protocols, too.
svgs are just too different to be read by pillow. They fail on w3m too, and the only terminal that supports them seems to be terminology. Support might be coming if there is a simple way to generate a raster image from them. Maybe if the user has inkscape installed it could be possible to generate a png in a reasonable timeframe? Alternatively a native library could be the solution. This could also benefit other protocols, too. |
I'd make the error message something along the lines of "Image previews require PIL". Having the scaling be configurable would be good with at least three options: no scaling, downscaling only and both. Backporting would be ideal but if that requires PIL it'd definitely have to be optional like most of ranger's dependencies, silently falling back to sane behavior if it's not available. SVG support for other methods would also be great if the performance is good enough but this is definitely an enhancement, not of the highest priority. These last two things would be seperate PRs of course. @tkerber, thank you for testing. Image previews are probably the most common reason for issue reports so we want to be careful adding new methods lest they introduce even more issue reports : ) |
I'll try to tackle the rectangle resize menace right now, and see if I can cook up some solution for that |
Just dropping in with some tips, that might be helpful:
And let me finish by saying that it is cool to see the kitty image protocol being used in the wild. I am happy to take suggestions for improving the protocol based on actual usage. |
doc/ranger.pod
Outdated
@@ -229,14 +229,11 @@ To enable this feature, set the option C<preview_images_method> to urxvt-full. | |||
=head3 kitty | |||
|
|||
This only works on Kitty. It requires PIL (or pillow) to work. | |||
It is able to automatically work over network, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: I'd stick closer to the original phrasing. "Allows remote image previews, for example in an ssh session." I'm not sure the performance implications should be in the manpage but I could be convinced otherwise.
@kovidgoyal thanks for the tips! I think I am going to leave svgs to a later commit, but this is helpful to know. Talking about @toonn Noted! Also I found out that kitty display images in their native size if a rectangle is not specified, so the next commit will solve all issues about resizing artifacts. |
8a0b41d
to
a57cf76
Compare
I got working previews without artifacts. Smaller images are not scaled at all, while big images are fit in the best way to the preview pane. It was deceivingly simple to implement, contrary to my belief! Anyway if the test from other users go well and everything else code-wise is fine, I would say this is a great point for merging, since future improvement are kinda worth they own pull request. |
doc/ranger.pod
Outdated
=head3 terminology | ||
|
||
This only works in terminology. It can render vector graphics, but works only locally. | ||
To enable this feature, set the option C<preview_images_method> to terminology. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar nazi patrol : )
Missing new line before this one. Don't actually care about whether there's one or not but we should keep it consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All other sections have this line in a separate paragraph.
ranger/config/rc.conf
Outdated
# Preview images in full color using kitty image protocol. | ||
# Requires python PIL or pillow library. | ||
# If ranger does not share the local filesystem with kitty | ||
# the transfer method is switched to encode the whole image in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd drop "in the protocol that" then add "this" before allows. Something about the sentence seems off otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to have at least 2-3 more people test this. If that takes too long I'll get at least one other maintainer to review the code because this is a valuable addition and I don't want it to get neglected for lack of exposure.
image previewed correctly on kitty as well here. Thanks ! It seems like it tries to display all files thrown at it, regardless of the extension. Shouldn't it align with what One comment: maybe catch
|
Got it working on my setup without any issues, it works, I've tried some edge cases and so far it works really well! |
Tested on gentoo, working good. |
doc/rifle.1
Outdated
@@ -129,7 +129,7 @@ | |||
.\" ======================================================================== | |||
.\" | |||
.IX Title "RIFLE 1" | |||
.TH RIFLE 1 "rifle-1.9.0" "2018-01-25" "rifle manual" | |||
.TH RIFLE 1 "rifle-1.9.0" "02/16/2018" "rifle manual" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my precious ISO dates NotLikeThis
doc/ranger.pod
Outdated
=head3 terminology | ||
|
||
This only works in terminology. It can render vector graphics, but works only locally. | ||
To enable this feature, set the option C<preview_images_method> to terminology. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All other sections have this line in a separate paragraph.
doc/ranger.1
Outdated
.PP | ||
To enable this feature, set the option \f(CW\*(C`preview_images_method\*(C'\fR to kitty | ||
.PP | ||
\fIkitty-network\fR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this file needs to be regenerated because this section doesn't exist in the ranger.pod
anymore (there are also some typos above).
@freed00m that's weird, it looks like the console got garbled up. Can you tell me if the files that cause this have something in common? Size maybe, or an aspect ratio? Are they in a specific folder, or have weird filenames? |
@mark-dawn It's not file specific, here an example file https://ibb.co/bLpb3d . This file can be renamed confortably at I am running Manjaro Testing branch so I am cca week behind Arch in terms of versions, currently I use I am thinking maybe the rendering of font Awesome is triggering this? Or maybe my font of choice "Fira font medium" causing this? If you have some cool breakpoints I could debug I could :) |
I've tried disabling devicons and even changed fonts to no effect. :O what the heck is going on? |
Can reproduce. With all the weirdness. It is partially my fault: I am saving the temporary resized thumbnail that kitty reads and then deletes there. |
@mark-dawn Couple of suggestions:
|
Simplest solution that comes to mind is use a hash instead of the filename. That way you avoid most collisions with little effort. (I assume filenames that equal hash(filename) are rare and people don't store many files with hashes as names in |
@toonn The filenames are already hashed. I tried fixing it by using a fixed file that gets rewritten, instead of creating a new file every time. This indeed reduces the flickering, but the file updating still causes refreshes every now and then that corrupt the interface when trying to issue a command. |
Ah, didn't understand you're continuously deleting the thumbnails. |
I found the core of the issue, somehow when the cursor get moved to a new spot to draw the image it might "fail" to get back before the next refresh. In quotes because it might just be late. This restrict the fuckup to curses, since it is the only component that might be asynchronous. So when the cleanup code is called, curses/terminal is instructed to put back the cursor where it was before (async), then the |
Why would a subdirectory help exactly? |
AH! FIXED! (sort of)
The problem is that putp must not put stuff directly in stdout, so when python flushes the restore command might not be in stdout yet. The solution is simple, switch putp for a write to python stdout interface so everything goes along in the correct order. @toonn Oh, I could just not preview anything in the subfolder. Not ideal, but we could avoid disabling previews in the entire /tmp. We could even snuck it in |
@toonn I have a new version ready to push that should clean some bugs, but when I run test pylint goes absolutely berserk and reports errors all over the source tree. Pytest and flake8 are fine and everything is rebased on the latest master. Do you have any idea on why that might be the case? |
Line 12 in 8e9451e
Just use |
Thanks, that fixed up everything, except my blindness. I will probably make a new pull request since I am on a new branch. |
@Moelf, yes. The kitty method only works in kitty so the default is still w3m of course. I've thought about adding an |
Just FYI, the kitty graphics protocol supports detection at runtime. See icat/main.py (the detect_support() function for how the kitty icat tool itself does it). |
@toonn we could at least merge the @kovidgoyal that would be actually very useful, I still check at runtime if kitty is actually there but I ask the user to set an env variable, which is shitty. I'll take a look asap, thanks. |
I don't think we can merge them. That'd mean you can't toggle the setting, because what does toggling mean for a setting that can be an ever expanding number of options? |
Makes sense, but how can I tell ranger to use Kitty method since I always use Kitty anyways? |
@Moelf, add/change |
Hey, I know this thread is kinda old, but does anyone know how to use this feature with Kitty? I'm kinda lost. |
@theonecalculator
|
Worked flawlessly! My bad. |
ISSUE TYPE
RUNTIME ENVIRONMENT
CHECKLIST
CONTRIBUTING
document has been read [REQUIRED]DESCRIPTION
rc.conf
have been updated to advertise this new option.img_display.py
module that was used in three subclasses as an helper function.\n
). This has been fixed; also the lack of documentation for the terminology support was fixed too, adding it to both the manpages andrc.conf
Notes and issues
Since kitty only likes png or raw RGB data
PIL
is required as a dependency. I also plan on implementing an extra backend using the externalImageMagick
toolkit, like kitty does for his own icat utility. I left it for a later time since this method has been shown to fail occasionally, and is potentially slower since it has to invoke external processes. In any case,PIL
is only imported at the class level and not at the module level, leaving other options alone.It is also possible to change
KittyImagePreview
to automagically select between streaming and local file, but due to a bug and my incompetence withstdin
this feature is delayed, and the choice is made inrc.conf
MOTIVATION AND CONTEXT
The changes have been motivated by the fact that kitty has native support for images, meaning less edge cases, and in general w3m doesn't work on terminals that refresh independently of input, like kitty. This brings full image preview to kitty, basically.
#983 Relevant discussion
TESTING
The new branch has been used both on python2 and 3 (packages installed with pacman are
python-pillow
andpython2-pillow
).The standard test suite has been run.
The core of the codebase is mostly untouched, except for intialization of
ImageDisplay
classes infm.py
naturally. The_get_image_displayer
function has been updated with the relevant branches and excluded from pylinttoo-many-return-statements
since ""fixing"" the warning would amount to add a local variable and make the function one line longer and potentially slower.The other touched part is obviously
img_display.py
with most changes being orthogonal to the original code, except for the excision of a small common helper function to temporarely move the cursor (now wrapped nicely as a context manager). Terminology, which had the most complex use case has seen no change to its (buggy and now fixed) behavior. I couldn't test iTerm2 graphically but the text output looks fine.IMAGES / VIDEOS
kitty showing images for more than half a millisecond (you will have to believe me on the persistence of the output)