-
-
Notifications
You must be signed in to change notification settings - Fork 121
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
figure out pixel integration with the z-axis #1388
Comments
We see this problem even already in the |
...hrmm, maybe not. i change the foreground color each iteration, which ought cause damage, and yet we still see the same result :(. |
there's the complicating factor that the procedures and indeed capabilities are different between sixel and the kitty protocol. they're entirely different systems.
|
Not sure I understand the problem. Why do kitty and sixel semantics have
to be identical? I dont think that's even possible, since sixel doesnt
event support full resolution images. So why does it matter that they
also differ when printing text over images? Simply have that behavior be
undefined and clients that rely on it are broken. Or if notcurses is
keeping track of image and cursor positions, have the library throw an
error if it detects text will overlap an image. Maybe have a way for
clients to override that error and force text over image, with the
caveat that behavior will be different based on the imaging backend.
|
they don't have to be identical, of course, but i'm trying to offer an abstraction layer atop the two. if someone's blitting to a plane with with that said, only with the kitty protocol can i sanely stack image graphics, as far as i'm aware, so that's a definite plus -- i think that'll just break under most sixel implementations. but i'm going to make it available nonetheless. btw here's some nice text above an image using kitty |
So in kitty you can have text above and below different images. I think what you are asking for is to give text z-indices too. I dont think that's a bridge I am ready to cross in kitty. You could simulate its effects by chopping up the image per cell and setting different z-indices on each cell image. |
And I should add w.r.t. chopping up images into cell sized pieces, this is not a scenario the data structures that track images in kitty are optimized for, so I dont know what the performance would be like. |
i think i've got a workable scheme here: Fundamental facts
Classes
Actions
we'll want to take advantage of kitty's ability to load and redraw an image; we have no such luck with sixel, and must resent the image in its case, lame. |
To do this sanely, I think we'll take the following steps:
|
You don' have to redraw the whole image, only the part(s) that has been erased/overwritten. I believe this is one of the reasons Jexer splits up images into stripes mapped to cell rows. FWIW, at least XTerm (and foot), will not include empty pixel rows in the last sixel row in the final image, meaning you can emit images with a height that isn't a multiple of 6. But this is likely an area where different terminals behave differently. |
hrmmm, this seems to contradict my own xterm experience. let me go verify.... |
alright, i think the thing to do is to keep a two-bit-per-cell map of each sprixel in the sprixel cache. for each cell, we want to know if it's (0) opaque, (1) transparent or semi-transparent or (2) annihilated. that allows us to quickly perform mop-up invalidations and redraws as necessary, and at a per-cell granularity. Also, I'm wondering whether we can't make use of kitty's full 8 bits of alpha to effect an image above some text and (translucently) below others....i think it will work. Finally making progress here! |
OK, after the work on #1401, we're getting pretty close.
it would also be very good to use kitty's presentation commands to move around an image in response to plane moves, but that's more for #1395. |
so the next step is to make the transparency/annihilation map for each sprixel, as mentioned above. let's go into some more detail. for each cell in the ncplane, on initialization we set up a transparency map, marking a cell 0 if no pixels are transparent, and 1 if at least one pixel is. we'd need build this map up in we still need to determine the intersection of the rendering area and these transparency maps, which sounds messy. ideally we'd drive this from the sprixel pass, so that we only ever do work when sprixels are in play. to do that, we'd need stop setting |
...YOU KNOW... kitty's transparent text atop graphics looks awesome, no doubt about it. much cooler than the sixel equivalent (z==-1): and it does sit "atop" the background color...and it vastly simplifies things...the only problem is that it teaches you that you can draw text all over a graphic and it'll work, which it won't for sixel...but that's fine. we can just say "text with a transparent background might or might not work; it might blow away chunks of the image it's drawn on". so they avoid it except where it's necessary...and then maybe other terminals catch up in the future, hrmm. in this case we still need to redraw under the graphic (followed by a redraw of the graphic where affected) for changes beneath the graphic, but we don't have to do anything for text atop it. we don't need to track annihilation, we don't have to do null-alpha cuts on kitty graphics, that's all much simpler. and in kitty and kitty-like protocols, things can look much cooler. hrmmmmm. you would have to wipe out all text underneath opaque parts of a kitty image manually, bleh. hrmm, also, with kitty, if you wanted a background up above the image, that apparently requires an alpha cut, since it's sticking the background color behind everything else, see below: |
You can have background above image by specifying a suitably negative z-index for the image. Quoting from the spec: Finally, you can specify the image z-index, i.e. the vertical stacking order. Images placed in the same location with different z-index values will be blended if they are semi-transparent. You can specify z-index values using the z key. Negative z-index values mean that the images will be drawn under the text. This allows rendering of text on top of images. Negative z-index values below INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background colors. |
you're absolutely right, of course; thanks for the heads-up! i'd read this, but dismissed it as not relevant to my needs, but with this possible new approach, it suddenly becomes useful. |
of course, if i do this, i can't have text show behind (only) transparent regions of the same graphic. =[ i.e. i can't have a single graphic whose transparent regions show text (while being opaque in the pixels they cover, in the same cell) while also allowing text to draw foreground+background on other regions of the graphic. that's the fundamental issue i have with the kitty protocol, which is otherwise a tremendous improvement over sixel imho. |
On Thu, Mar 18, 2021 at 04:56:06AM -0700, Nick Black wrote:
> Finally, you can specify the image z-index, i.e. the vertical stacking order. Images placed in the same location with different z-index values will be blended if they are semi-transparent. You can specify z-index values using the z key. Negative z-index values mean that the images will be drawn under the text. This allows rendering of text on top of images. Negative z-index values below INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background colors.
of course, if i do this, i can't have text show behind (only) transparent regions of the same graphic. =[ i.e. i can't have a single graphic whose transparent regions show text (while being opaque in the pixels they cover, in the same cell) while also allowing text to draw foreground+background on other regions of the graphic. that's the fundamental issue i have with the kitty protocol, which is otherwise a tremendous improvement over sixel imho.
As I said before, that would require giving text also z-indices. That is
not something I am willing to do. Without it, you have the following
options to achieve it:
1) Cut up the image into sub-images
2) Render the text as an image yourself and blend as desired
|
yep, i get it =] and cutting up the image (or setting a region of it to alpha=0) is exactly what i'm planning. |
holy jesus, i just had a realization: if we cut the picture down to component cells, you could 1 always have a perfect set of color registers in sixel, and 2 deal with pixels like you do any other cell-oriented thing. we'd just need to make sure terminals can deal with thousands of images at the same time. there'd also be significant overhead due to loss of RLE, fixed sprixel setup, and repeated color registers. but yeah, do that, and suddenly we're rid of all this special-purpose code. need to do the experiment first, though. |
better.mov |
w00t! |
the i wouldn't be surprised if a large part is due to slowness in the wiping. when we put the cache in, things got massively better. xterm looks kinda ehhh either way, sadly. |
https://www.youtube.com/watch?v=Uh8jV-evm1E looking just about perfect with kitty now |
We're now building up the |
i've implemented the invalidation for when a cell underneath a bitmap is updated, fixing |
Still need a working We need do some experimentation (at the shell) to lock down exactly how Sixels work when you print one with a missing portion over another.
|
OK, i know the reason why |
....i think i might have got it. Everything appears to be working perfectly in both sixel and kitty. Doing some final testing... |
I first bring this up in #1380, but it really demands its own issue. How are we going to integrate the realities of Sixel with our z-axis/transparency model? Sprixels are written out atomically, covering whatever pixels they don't specify (i.e. not necessarily blowing away entire cells). Cells written atop a sprixel are blown away entirely.
I don't really see any way to do our entire z-axis model. Sprixels atop cells work just fine, but we can't write glyphs with transparent backgrounds atop sixels and retain them, at least so far as I can see. So the simple interpretations is simply: sprixels aren't integrated into the model. If another cell is atop sixels, the sixels don't get factored in. If sixels are atop other cells, the cells below aren't factored in.
But that's kinda lame, since we do have transparency within a sprixel. BUT doing this properly is complex: we'd have to emit all the cells underneath the sprixel, and only then draw the sprixel atop them. BUT you can't just emit the sprixel after writing everything but sprixels, because then you blow away things that were above the sixels. You almost have to layer them: cells below sprixels, sprixels, cells above sprixels. And if you have sprixels at multiple levels of the z-axis, this quickly gets to be a pretty big pain in the ass.
For 2.2.3, I think it's sufficient to get something simple up, but this problem demands hard thought.
The text was updated successfully, but these errors were encountered: