Skip to content

Quick view: show images on terminals with inline graphics (iTerm2, kitty protocols) - #5198

Open
zed-0xff wants to merge 2 commits into
MidnightCommander:masterfrom
zed-0xff:images-quick-view
Open

zed-0xff wants to merge 2 commits into
MidnightCommander:masterfrom
zed-0xff:images-quick-view

Conversation

@zed-0xff

@zed-0xff zed-0xff commented Oct 21, 2026 •

Copy link
Copy Markdown

Proposed changes

Show images in the quick view panel (C-x q) on terminals that can display inline graphics.

image
  • iTerm2 inline images protocol (OSC 1337): iTerm2 (also over ssh via LC_TERMINAL) and WezTerm. The terminal decodes the image, so PNG, JPEG, GIF, WebP, TIFF and BMP all work.
  • kitty graphics protocol: kitty and Ghostty. PNG only, no format conversion is done. The image is fitted into the panel keeping its aspect ratio (size is taken from the PNG header and the cell size from TIOCGWINSZ).
  • Images are recognized by their magic bytes, not by the file name. Files bigger than 16 MiB are not previewed. Files are read via VFS, so images inside archives and on remote VFS work too.
  • Only in the quick view panel, never in the full screen viewer. F4 (hex mode) shows the raw bytes as before. Inside tmux/screen the feature is disabled, because escape sequences would need passthrough.
  • When the image goes away (another file selected, hex mode, panel closed), it is removed from the screen: explicitly for kitty, by clearing the terminal and repainting for iTerm2 (which keeps the image under any text written over it).
  • New mc.ini option quickview_image_protocol = auto (default) | iterm2 | kitty | none to override the autodetection. Documented in the man page.

Implementation is in the new src/viewer/image.c, with small hooks in the viewer (mcview_load, mcview_display, mcview_done, widget destroy).

Testing: unit tests for magic bytes sniffing, PNG size parsing, fitting, protocol detection and the ini setting, and loading of files (tests/src/viewer_image.c). The drawing itself writes escape sequences to the terminal and is not covered by unit tests; it was checked by hand in iTerm2 only. The kitty path (Ghostty, kitty) is untested in a real terminal.

  • Resolves: #...

Checklist

👉 Our coding style can be found here: https://midnight-commander.org/coding-style/ 👈

  • I have referenced the issue(s) resolved by this PR (if any)
  • I have signed-off my contribution with git commit --amend -s
  • Lint and unit tests pass locally with my changes (make indent && make check)
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation (if appropriate)

🤖 Generated with Claude Code

@github-actions github-actions Bot added needs triage Needs triage by maintainers prio: medium Has the potential to affect progress labels Oct 21, 2026
@github-actions github-actions Bot added this to the Future Releases milestone Oct 21, 2026
@zed-0xff
zed-0xff force-pushed the images-quick-view branch 2 times, most recently from 37cc023 to d7a4883 Compare October 21, 2026 17:25
Signed-off-by: Andrey "Zed" Zaikin <zed.0xff@gmail.com>
@ossilator

Copy link
Copy Markdown
Contributor

why would you do that instead of binding an appropriate external image viewer?

@zed-0xff

Copy link
Copy Markdown
Author

@ossilator because I don't want to change context, I only want a quick image view

@ossilator

Copy link
Copy Markdown
Contributor

you don't have to. there are viewers that would do the job. my first google hit for "kitty image viewer" is kitten-icat (totally unsurprisingly).

@zyv

zyv commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Oh, finally, something Claude-generated that answers my personal needs and doesn't look too bad; thank you for trying. And something for @egmontkob, I assume :)

Out of interest, which model/effort was that, Opus 5.5 @ High? Did you perform a /code-review? If you didn’t, could you please do so? Sadly, I've got no tokens.

  • kitty graphics protocol: kitty and Ghostty. PNG only, no format conversion is done. The image is fitted into the panel keeping its aspect ratio (size is taken from the PNG
    header and the cell size from TIOCGWINSZ).

So I'm actually very positive about the iTerm protocol, because it requires very little on our side. And I'm less positive about kitty, because it seems that we need this micro-parser for PNG headers to get the aspect ratio.

Is this unavoidable? Can Claude cook up a supported terminal matrix? I can migrate to iTerm, but I presume then that everybody else is left in the cold, so we have to pay the parser fee?

  • Only in the quick view panel, never in the full screen viewer. F4 (hex mode) shows the raw bytes as before.

Why not? We have Raw & Parsed mode for both. I think it would make sense to make the viewer behave the same in panel and full mode:

  • For Parsed - show render on supported terminals and what we had before on unsupported.
  • For Raw - show raw.
  • New mc.ini option quickview_image_protocol = auto (default) | iterm2 | kitty | none to override the autodetection. Documented in the man page.

I would actually not want this. Why is that useful? Is autodetection expected to fail often and cannot be fixed by the user otherwise? We have tons of obscure options that nobody uses, and this will be another one. What we can debate is whether we need an option to turn off the rendering altogether.

  • I have referenced the issue(s) resolved by this PR (if any)

So you didn't search for any relevant issues? You could have asked Claude to do so. I would assume there must have been some requests for an embedded image viewer in the past.

@zyv

zyv commented Oct 21, 2026

Copy link
Copy Markdown
Member

why would you do that instead of binding an appropriate external image viewer?

You mean modifying mc.ext to call an external viewer in Parse mode? I thought this ain't gonna work, because you'd need the raw escape sequences forwarded to the host terminal.

Signed-off-by: Andrey "Zed" Zaikin <zed.0xff@gmail.com>
@egmontkob

egmontkob commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Back around 2019-2020 developers of various terminal emulators had heated, neverending discussions about how to do image displaying in terminals. It's still available in the "terminal-wg" forum as issues 12 & 26, maybe even more (deliberately not linking, I don't want you to waste hours).

I also expressed my pretty firm opinion there, the core concept being that image display had to find its way to stay inside what we already know as terminal emulation (with its strict charcell-based architecture) and its surrounding infrastructure, including features like headless terminal emulation (e.g. detached tmux) and whatnot. Not many people agreed with that. As per a segment quoted above from Kitty:

the cell size [taken] from TIOCGWINSZ

the image is bound to be broken if you change the terminal's font aspect runtime, and the method conceptually cannot work in environments where the notion of cell size doesn't exist (e.g. detached tmux to be attached back in the future; tmux session concurrently attached from multiple different terminals; headless emulation libraries such as libvt), isn't known (e.g. telnet, netcat), or is known incorrectly (e.g. replaying a script log). As such, without knowing anything more about Kitty's image protocol, solely from the bits quoted above, I already consider it a fundamentally bad protocol.

I'm not familiar with iTerm2's solution.

There wasn't any agreement whatsoever, a few terminals went ahead with their own individual solutions. Presumably mc would need two different codes for Kitty and iTerm2, and a new one any time another terminal comes up with its own sh_t.

I lost interest in the whole topic, I no longer care about displaying images in terminals. Consequently, unfortunately I don't care about this feature of mc either.


VTE ships a funny little img.py tool. It's a low-res image viewer, assuming a 2:1 ratio of character cell size and using the "half block" Unicode character. That is, every character cell contains two large square-ish "pixels": one color in its upper half and one in the lower half.

It works in every terminal that has truecolor support. Which is a much-much wider range of terminals than Kitty + iTerm2. Obviously, the result is not what people of the 21st century would expect from an image viewing feature.

If we wanted to have this coarse image viewer in mc, the bottleneck would be (sigh, back at this topic again, see also #3264) the braindamaged palette-based approach of both ncurses and slang, rather than proper direct truecolor support.

So... one question is... using Kitty's or iTerm2's protocol: Could mc somehow still use these graphic libraries and make sure it doesn't conflict with however those pictures are displayed? If so, would it be because those image protocols somehow present something that is "in front of" the regular display, or how? Would be weird, I guess. I don't know, I'm not familiar with the details of those protocols.

@ossilator

Copy link
Copy Markdown
Contributor

You mean modifying mc.ext to call an external viewer in Parse mode?

no. just launch a normal foreground application and be done with it. in fact, image.sh already has support for multiple console viewers. mc doesn't need to know what protocol the app uses to actually display the content.

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

Labels

needs triage Needs triage by maintainers prio: medium Has the potential to affect progress

Development

Successfully merging this pull request may close these issues.

4 participants