# So, this *is* possible, but...

_General · started by Mark on Fri, Sep 4, 2026 9:27 PM_

---

## Original post

**Mark** · Fri, Sep 4, 2026 9:27 PM

Is it something we want?

---

## Reply 1

**Mark** · Fri, Sep 4, 2026 9:28 PM

![nnimgs.png](/storage/forum/XClxgw3Xynkh1DZYiNnKMj5pwp90moVGIiIVxg3T.png)

---

## Reply 2

**Mark** · Fri, Sep 4, 2026 9:32 PM

The screenshot is not a mockup, it's running live in nomadnet, but it *is* just a prototype for testing out whether it was actually viable.

Currently, it's only the client-side parts that are implemented, which, while not the simplest thing to get working, is really only a pretty small part of it.

The more important part is getting the whole serving side right, so that low-bandwidth connections aren't choked. That means it needs automatic scaling and compression for low-bandwidth peers, selective image retrievals, and having everything configurable and user-selectable, so pages with images can still be fetched in light-weight text-only mode.

---

## Reply 3

**Mark** · Fri, Sep 4, 2026 9:37 PM

Forgot to say, currently, I've only tested it in Kitty and Konsole. It *should* work in any terminal that supports the Kitty Terminal Graphics Protocol. I'd be really hesitant to add other terminal graphics protocols to the rendering backend, since most of those would require really heavy dependencies to handle image slicing, scaling, et cetera, et cetera. As it's implemented now, there's *zero* new dependencies; everything is handled in pure Python, performs really well, and is light on resources and memory. The terminal itself does the heavy lifting.

It also supports image buffer re-use, so the raw image data is only written to the terminal once, and can be re-used for as many image instances as required in a very light-weight way.

It supports basic sizing and alignment, such as setting width/height in cols/rows or percentages, and setting left/right/center alignment.

I'd love to hear what people think about this.

---

## Reply 4

**MOI** · Fri, Sep 4, 2026 10:09 PM

Hello Mark!

I think it's great, especially in the case of 'zero new dependencies'.

Question: How to determine if a terminal supports the Kitty Terminal Graphics Protocol? Do most Debian-based Linux distro's support this protocol?

---

## Reply 5

**Anonymous** · Fri, Sep 4, 2026 10:49 PM

Well I am not sure just having images is going to work it certainly doesn't meat your own requirements, however; Those requirements are something the wider net limited itself to and it grew as the infrastructure grew. In that time we came up with solutions that made content scale with capability. You could enforce progressive encoding for images and at the bottom render a skeleton in its place. There are so many tricks to this these days not worth going over them all here but some scaling maybe based on connect bandwidth would be in order. I believe you can drive progressive scaling algorithms in css these days even.

---

## Reply 6

**Mark** · Fri, Sep 4, 2026 11:01 PM

All (practically speaking) operating systems will have terminal emulators available that support graphics rendering. There's various protocols available for this, and different terminal emulators supports different sets of them. Some of the older, but relatively widespread protocols are Sixel and iTerm2. Both of those have some serious shortcomings; inability to efficiently place and erase graphics in interactive applications, only 256 colors, missing alpha support, various quirks and weirdnesses. The most efficient and complete terminal graphics protocol is currently Kitty. It was initially implemented in the Kitty terminal emulator, but now quite a few terminals support it, across all major platforms (not sure about Android though).

So, whether or not it is supported is not an OS thing as such, it's a question of whether your terminal emulator supports it. There's definitely a terminal application on your desktop OS of choice that does support it, but it may not be your current *favorite* terminal emulator.

It's a bit hard to find a conclusive overview, since terminals have features added all the time. I can say for certain that it works perfectly well in Kitty, Konsole (default on KDE-based distros) and Wezterm, just tested those. Ghostty seems to have support as well.

I even found a GH issue discussing the implementation of KTGP in the default *Windows* terminal, so it's apparently becoming pretty widespread ;)

In my current implementation, if the terminal cannot render the image, it just falls back to a text placeholder with the alt-text instead.

---

## Reply 7

**steveplays** · Fri, Sep 4, 2026 11:31 PM

I saw a nomadnet node last week where the operator added truecolor images to their blog, with clickable buttons to show the images, it was quite nice. I didn't save the address, but if I find it again, I'll send it for reference.

That said, maybe there should be clickable buttons for displaying images?
Also, truecolor and ASCII fallbacks could be useful, if that doesn't complicate it too much

---

## Reply 8

**Zenith** · Fri, Sep 4, 2026 11:34 PM

I really like the idea, but my vote is a no. Not as how you are suggesting it. 

VTE barely supports anything as-is (a GNOME certified classic) and that's what more than half of Linux distros ship with.  

If there were to be an image tag, I would suggest it to be opt-in, and function more as an inline preview than a static page asset. Nothing should download without the user directly requesting it. 

My suggestion would be an "inline image preview" instead of inline images. 

A preview would look like a link, but show the filename and filetype. Clicking on it would send a request to the node to fetch the image, and it could then be rendered inline. When inline images are enabled, a placeholder for the image boundaries could also be shown.

 The progress of the Resource transfer could even be displayed  too with some type of nice progress bar. 

The preview could be collapsed like the new accordions, or expanded into some type of fullscreen dialog to see a better view, which could then be closed. 

I don't know the specifics off the top of my head but it would also be good to check to make sure that kitty graphics has both WebP and AVIF support.

---

## Reply 9

**MOI** · Fri, Sep 4, 2026 11:40 PM

**Mark** wrote:
> All (practically speaking) operating systems will have terminal emulators available that support graphics rendering. There's various protocols available for this, and different terminal emulators supports different sets of them. Some of the older, but relatively widespread protocols are Sixel and iTerm2. Both of those have some serious shortcomings; inability to efficiently place and erase graphics in interactive applications, only 256 colors, missing alpha support, various quirks and weirdnesses. The most efficient and complete terminal graphics protocol is currently Kitty. It was initially implemented in the Kitty terminal emulator, but now quite a few terminals support it, across all major platforms (not sure about Android though).
> 
> So, whether or not it is supported is not an OS thing as such, it's a question of whether your terminal emulator supports it. There's definitely a terminal application on your desktop OS of choice that does support it, but it may not be your current *favorite* terminal emulator.
> 
> It's a bit hard to find a conclusive overview, since terminals have features added all the time. I can say for certain that it works perfectly well in Kitty, Konsole (default on KDE-based distros) and Wezterm, just tested those. Ghostty seems to have support as well.
> 
> I even found a GH issue discussing the implementation of KTGP in the default *Windows* terminal, so it's apparently becoming pretty widespread ;)
> 
> In my current implementation, if the terminal cannot render the image, it just falls back to a text placeholder with the alt-text instead.

Thank you very much for your extensive and very clear explanation, Mark!

---

## Reply 10

**Zenith** · Fri, Sep 4, 2026 11:51 PM

**Zenith** wrote:
> I don't know the specifics off the top of my head but it would also be good to check to make sure that kitty graphics has both WebP and AVIF support.

Ah wait nvm I forgot that's just APC sequences so really you can display anything as long as you can encode and decode it yourself

---

## Reply 11

**mecayotl** · Sat, Sep 5, 2026 2:38 AM

I very much like this idea and Zenith's addition to it. Being able to show things graphically would nice to have on nomadnet. For example, I wanted to show text art on my site, so I created an ANSII/ASCI text to Micron converter for myself. I was just thinking of a way to convert an image -> ANSII -> Micron, with some ways to compress the image or show the byte count in the UI with a rough estimate of transfer time at LoRa speeds. 

Maybe you could show the Micron image of it to keep it text based and then opt to download the real thing like Zenith was suggesting :P 

Mostly kidding but excited to see what ends up being decided. I especially like what Zenith said, nothing should download without the user directly requesting it

---

## Reply 12

**Aquamaniac** · Sat, Sep 5, 2026 5:03 AM

May I instead propose to make it configurable in Nomadnet to pass media directly to some util for one-time only viewing instead of this or downloading and storing media on-disk and only then opening it manually? E.g. pipe it into your favourite media player, or write it directly into X server's fb if you really want to. Hell, it doesn't even have to depend on a graphical environment at all, it could be sent to kernel's DRM, or be represented as terminal graphics (again, assuming one's term supports it) through img2sixel and whatnot, or perhaps even something completely different entirely.

I use elinks in combination with mpv and yt-dlp (the latter is not even needed for direct links) to surf WWW.
There are two types of sites: those that rely on browser's media player and those that reinvent the wheel (most notably YouTube, Twitter, Facebook, Fandom, Reddit, other social media BS, etc...) and use their own often laggy and buggy JS players, everyone doing their own separate thing. Instead there could've been a standardised way to pass media to user's preferred player and we likely could've had all the nice things like smaller and simpler browsers, less clutter on-page and HW decoding but handled by an external media player (remember when Firefox's HW accel used to break every other update on Linux?).

In my humble and lowly opinion a simple direct link and ability to pipe it would more than enough, and far more flexible. Though I suppose one doesn't have to exclude the other.

---

## Reply 13

**r8io** · Sat, Sep 5, 2026 9:18 AM

@Mark I am strongly in favor of your idea. I would **love** to see image rendering being added to nomadnet. After looking at the above suggestions, here is how I think it could be done: - Add a global setting to the nomadnet config file to enable/disable automatic image rendering. - Add a per node setting to enable/disable automatic image rendering that overrides the global setting. This setting could be placed in the "Node Info" tab below the "Trusted" setting. - Add a placeholder for every image to the page if automatic image rendering is disabled. The placeholder could consist of two links. One to download the image and the other to show the image inline. Example: ʼnnimgs.png (872.9 KB)ʼ  ʼShowʼ. - Add a download link below every rendered image. Example: ʼnnimgs.png (872.9 KB)ʼ - "zero new dependencies", as you suggested, is the way to go.

---

## Reply 14

**CarL_PetErson** · Sat, Sep 5, 2026 10:21 AM

I'm worrying that pictures might start a trend to make Nomadnet sites more flashy and at some point browsing nomadnet will become too slow for Stuff like LoRa.

But what Zenith and r8io suggested sounds great.

One addition: some mechanism to choose from different file sizes (if present) would be nice.

---

## Reply 15

**r8io** · Sat, Sep 5, 2026 11:37 AM

Ups, after editing a typo in my post above all line breaks are gone :) Here is a repost, for better readability:

@Mark I am strongly in favor of your idea. I would **love** to see image rendering being added to nomadnet.

After looking at the above suggestions, here is how I think it could be done:
- Add a global setting to the nomadnet config file to enable/disable automatic image rendering.
- Add a per node setting to enable/disable automatic image rendering that overrides the global setting. This setting could be placed in the "Node Info" tab below the "Trusted" setting.
- Add a placeholder for every image to the page if automatic image rendering is disabled. The placeholder could consist of two links. One to download the image and the other to show the image inline. Example: `nnimgs.png (872.9 KB)`  `Show`.
- Add a download link below every rendered image. Example: `nnimgs.png (872.9 KB)`
- "zero new dependencies", as you suggested, is the way to go.

---

## Reply 16

**aetherlab** · Sat, Sep 5, 2026 12:37 PM

**r8io** wrote:
> Ups, after editing a typo in my post above all line breaks are gone :) Here is a repost, for better readability:
> 
> @Mark I am strongly in favor of your idea. I would **love** to see image rendering being added to nomadnet.
> 
> After looking at the above suggestions, here is how I think it could be done:
> 

Same oppinion here! Hey, you got an HF rig?!

---

## Reply 17

**r8io** · Sat, Sep 5, 2026 1:37 PM

@aetherlab, no I don't have an HF rig. Unfortunately I know next to nothing about radio stuff, but I have that on the list for my next life. Maybe I will take a class in Walhalla ;)

---

## Reply 18

**Anonymous** · Sat, Sep 5, 2026 2:54 PM

Personally, I'm in favor, as long as it's used sparingly by NomadNet sites and not transmitted over slow links like LoRa, HF etc. unless a download is explicitly requested by the client, and caching and compression are smartly used.

Could be useful for Retipedia and forums (like this one), along with probably some other uses I can't think of

---

## Reply 19

**aetherlab** · Sat, Sep 5, 2026 3:50 PM

**r8io** wrote:
> @aetherlab, no I don't have an HF rig. Unfortunately I know next to nothing about radio stuff, but I have that on the list for my next life. Maybe I will take a class in Walhalla ;)

Oh sorry, I meant Mark's picture in Nomad! 73 de LZ1SWE

---

## Reply 20

**A. Non** · Sat, Sep 5, 2026 5:01 PM

**Anonymous** wrote:
> Personally, I'm in favor, as long as it's used sparingly by NomadNet sites and not transmitted over slow links like LoRa, HF etc. unless a download is explicitly requested by the client, and caching and compression are smartly used.
> 
> Could be useful for Retipedia and forums (like this one), along with probably some other uses I can't think of

I use lynx to browse, it's still quite useful.  It will display the alt text or caption for an image if available, perhaps enforcing a caption for images would be useful for nomad?  Text only users would not be left out and it increases accessibility.

---

## Reply 21

**Anonymous** · Sat, Sep 5, 2026 5:58 PM

I'm in favor of inline images upon request only. Maybe a built-in low-res preview as well?

---

## Reply 22

**Emru** · Sat, Sep 5, 2026 6:47 PM

I'd say no
Let's keep TUI a TUI, but I think it would be nice in GUI nomadnet (of course with configuration option to only download images smaller than X, or something like that).

---

## Reply 23

**G6PHF** · Sat, Sep 5, 2026 7:53 PM

**aetherlab** wrote:
> **r8io** wrote:
> > @aetherlab, no I don't have an HF rig. Unfortunately I know next to nothing about radio stuff, but I have that on the list for my next life. Maybe I will take a class in Walhalla ;)
> 
> Oh sorry, I meant Mark's picture in Nomad! 73 de LZ1SWE
It's a Yaesu FT991a by the looks of it, which is one of my radios :)
![IMG_3118_2.JPG](/storage/forum/TtZN5VhyhV70JhpzA0RwUWJsRuFAVGIa5JwBKQWI.jpg)

73
de G6PHF

---

## Reply 24

**Professor_Boop** · Sun, Sep 6, 2026 2:20 AM

Hey, on a slight side tangent: I think JPEG XL might be a great match for Nomadnet because of its progressive decoding. You store a single file, and the nomadnet site can send just the first ~1%-ish of the codestream (the low-frequency frame) to give a decodable coarse image on slow links like LoRa, or deliver the remaining bytes for full quality for users on high-bandwidth links. Truncated prefixes stay decodable, so it also degrades gracefully if a transfer cuts off partway.

---

## Reply 25

**Zenith** · Sun, Sep 6, 2026 5:49 AM

**Professor_Boop** wrote:
> Hey, on a slight side tangent: I think JPEG XL might be a great match for Nomadnet because of its progressive decoding. You store a single file, and the nomadnet site can send just the first ~1%-ish of the codestream (the low-frequency frame) to give a decodable coarse image on slow links like LoRa, or deliver the remaining bytes for full quality for users on high-bandwidth links. Truncated prefixes stay decodable, so it also degrades gracefully if a transfer cuts off partway. 

+1 for JXL!!!!!

---

## Reply 26

**d4e363fb** · Sun, Sep 6, 2026 2:13 PM

Inline images are not important to me (and would likely not work in tmux anyway).  I'd rather see a download handler that can pipe image data to a (preferrably progressive) image viewer, AV media to mpv, or whatever else is configured.

---

## Reply 27

**K8 - Mobile** · Sun, Sep 6, 2026 3:37 PM

Lmao, I love that you actually did this. I think it would be great to have, but like others have said only if it's opt-in, degrades gracefully, and has good support for progressive loading. Most of the time I think the kind of interface I'd want is probably being able to select an image and have it open in a modal box, with only a link, or maybe a small preview or a micron text rendering displayed inline.

You were talking about wanting to make a game, right? So maybe there could be a sort of consent ladder where users can opt-in to levels of image display and interactivity, and the page creator is responsible for making sure that everything still functions at every level.

---

## Reply 28

**Mark** · Sun, Sep 6, 2026 6:19 PM

Ok, everyone gets what they want - more or less, lol.

- Don't want image loading or display at all? Set `image_loading` to `never` in the config.
- Want to only load images manually? Set to `manual`.
- Want to load automatically if link conditions are suitable? `auto` is the answer.
- Don't care about the bandwidth? `always` has you covered.

The whole thing is gated by the terminal actually *being able* to render images. If not, no images are ever fetched or attempted rendered. This is queried and determined dynamically on startup, so no user config is necessary. If image display is not possible, or disabled in the config, images render as alt-text placeholders instead. The alt-text is mandatory, it must be specified for an image tag to be valid.

No matter what kind of image loading method is specified, images will **always** load asynchronously after the main page is loaded, re-using the existing link if possible. Images are loaded sequentially, one at a time, in the order they appear on the page. Once an image begins loading, its placeholder changes to a dynamically updating progress indicator showing transfer progress and speed. Once the image is fully loaded, *poof*! It appears on the page!

Images are cached locally, and will only download if the local cache is empty. I haven't fully worked out the cache specification mechanics yet, so that is still a pending item. For now, you can manually clear and reload for a page with `Ctrl-X`.

While I haven't finished implementing this yet, the request format is prepared for using a per-link key, so images cannot be deep-linked from other nodes than the one serving them; that is, you will be able to specify that images are only served to clients viewing a page on your node, and not from somewhere else. This will probably be the default.

The current implementation adds zero extra dependencies or bloat to the program. This was a *bit* tricky, since webp decoding is not exactly a five-liner in Python (or any language). What I ended up doing was to create a decoding multi-backend proxy, that *should* be able to resolve a working webp decoder on more or less any operating system. The nice thing here is, that almost every OS in existence already has *some way* of decoding webp (one good thing about web-browsers, I guess), so in most cases we can just find the distro-installed `libwebp.so` (or dylib, or dll), and hook into that via `ctypes`.

So yeah, in most cases, it's just using the OS-native decoding through the C ABI. It also supports using common utilities such as image magick `convert`, `ffmpeg`, `sips` and such. Yes, `PIL` works too :)

If you have a terminal that does support image display with Kitty TGP, but it's still not working, you can run `python -m nomadnet.ui.textui.images._selftest` and post / send me the results.

From the beginning, my intention with this was to **only** allow webp for network transport, and judging the feedback, I think that's still a pretty safe bet to begin with. There's some good points about JPEG XL, hadn't thought about that actually, but I'm not sure if it actually will prove to be more bandwidth efficient than WebP at high compression. I'll have to run some tests on that at some point to determine it.

Either way, adding JPEG XL will be a down-the-road thing once the whole basic functionality is proven and the kinks worked out. If you knew the hoops I had to jump through just to get webp decoding working without adding massive dependencies and bloat, you'd understand ;) Adding progressive JPEG XL loading and rendering will be a *massive* undertaking. Not impossible, just *massive*.

Regarding progressive / bandwidth selective loading, it may actually be simpler and more optimal overall to allow sending a `profile` key on the request (similar to LXST profiles), which will dynamically downscale and increase compression level at the node, before sending (that was my initial plan). Same result, at lot less over mechanistic overhead. Anyway, I'm open to the idea and will keep both in mind. But for now, webp it is ;) The selective profile-based loading is not implemented yet, but the system is prepared for it. At this point, it's probably better to wrap up an initial release of this, and see how it works in the wild, adjust and improve, and bundle all of that stuff into the next iteration, when there's more real-world data. So let's consider the current state of affairs the initial, experimental base-line.

Having a per-image download / modal view button is a great idea, if you just want an easy way to download images instead of viewing the in-page. I haven't implemented this yet, but that should definitely be added.

Media serving is now built into nomadnet itself as well, of course, so the built-in page node can serve images for pages. See the relevant guide sections on how to create micron image tags. The "Display Test" guide entry also tests image display now, so you can check easily if it works.

For `rngit`, the page node has also been updated, so it can natively serve images within rendered documents, display them in the file tree browser, et cetera. This is in the latest source version on Aleph. There's still a few finer points missing here, for example auto-conversion of image tags in markdown documents, but all the fundamentals are working (you can see the RNS logo in the Reticulum repo readme now). There's an automatic media converter here, that will convert non-webp images to webp for transmission, so more or less all images/graphics should work transparently.

If you want to try it out, all the source is on Aleph now. I'll probably wrap up a release for nomadnet shortly, so it can be tested a bit more conveniently, but the `rngit` changes will have to be fetched from source until the next release.

I took a lot of care to try and design and implement this in a way that is robust, degrades neatly, makes sensible use of resources, and doesn't destroy functionality or the experience for users who don't want or need it, while keeping `nomadnet` itself as light-weight as possible. That being said, there's bound to still be weirdness, bugs or edge cases I haven't considered, so I think it's best to let this have a real spin in the wild to see how it goes. Consider everything experimental regarding to this; we'll adjust and correct if something turns out idiotic.

---

## Reply 29

**Mark** · Sun, Sep 6, 2026 7:50 PM

Aaand, there's a wheel. 1.4.0 on Aleph and pip :)

---

## Reply 30

**Mark** · Sun, Sep 6, 2026 7:51 PM

If you want to try it out on a live node that actually serves images, you can try browsing some of the repos on Aleph that has images in their trees, for example `reticulum/docs/source/graphics` or something like that :)

---

## Reply 31

**burger** · Sun, Sep 6, 2026 8:07 PM

[removed]

---

## Reply 32

**Anonymous** · Sun, Sep 6, 2026 10:59 PM

It might be a good idea to use the QOI format.
It's especially useful for microcontrollers.
https://qoiformat.org

---

## Reply 33

**Zenith** · Mon, Sep 7, 2026 12:25 AM

Just an FYI that WebP and AVIF don't always compress better than PNG and JPEG. In about 85% of cases they do, but not always. Btw I was working on this exact same problem about 2 months ago for sending images via JXL and raster data over HF radio as a demo for my project, modem73. No Reticulum in that mix though. 
![image.png](/storage/forum/Ye36HhtBPDWbPYNwGEfcWxj2Ymovf292twF1P6jj.png)


https://www.tempertemper.net/blog/avif-and-webp-are-not-always-better-than-png-and-jpg

---

## Reply 34

**Zenith** · Mon, Sep 7, 2026 12:27 AM

If you want a really fascinating rabbit hole, take a look at the art people have made with JXL's predictive trees
https://jxl-art.lucaversari.it/wtf.html
https://jpegxl.info/art/

Welp time to add images over in Nomad for this forum! You should see that soon

---

## Reply 35

**Zenith** · Mon, Sep 7, 2026 12:50 AM

Also it would be really nice if instead of just showing: 

![image.png](/storage/forum/oLks166KxhfBIQqFXw4JIjsVQ2gbcJcpEDkoyy56.png)

We could have something like: 
![image.png](/storage/forum/8wDFTWffBtMQ89Skmfxu3NEjxx9eFvVkJ1D77lr0.png)


Edit:
Nvm, I just realized that the file size isn't known until we download the remote image. Any way that might be possible without requests? Would it make sense to cache that info in the page itself? Or have it as something that can be passed to the tag?

---

## Reply 36

**Anonymous** · Mon, Sep 7, 2026 3:15 AM

Not asking to change the WebP default, but a node-side profile that can emit a QOI (or even raw) thumbnail for constrained clients would let standalone hardware actually render images inline instead of alt-text only.

---

## Reply 37

**K8** · Mon, Sep 7, 2026 3:38 AM

This is working perfectly in iTerm2, I had no idea it actually supported the Kitty image protocol.

---
