Skip to content
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

proposal for animation: t=z to reference previous frames #3809

Closed
dankamongmen opened this issue Jul 7, 2021 · 16 comments
Closed

proposal for animation: t=z to reference previous frames #3809

dankamongmen opened this issue Jul 7, 2021 · 16 comments

Comments

@dankamongmen
Copy link
Contributor

Apologies if I've overlooked something in your docs/posts.

Use of the Kitty animation protocol has drastically reduced the necessary bandwidth for Notcurses's wipe+restore bitmap model (for those unaware, this refers to removing and then restoring cell-sized chunks). Unfortunately, my current implementation requires keeping a complete copy of the original RGBA data. I don't mind the memory consumption so much, but the copying is unfortunate.

This only really requires a single animation directive. I write the original image with a unique ID, and then:

\e_Ga=f,x=%d,y=%d,s=%d,v=%d,i=ID,X=1,r=1;",

supplying either a 0-alpha cell-sized region (to wipe), or a copy of the original cell (to rebuild). i only ever have a single animation frame. life is good. i was able to reduce bandwidth by over 99.9%. but we can do better.

What i'd like to be able to do is rebuild using the data available, without keeping any more state myself. I believe you suggested replaying the wipes onto the base when I needed to rebuild, deleting the old current frame, and displaying the new frame. That requires me keeping a list of wipes, and playing them.

The main difference is that the image the frame belongs to must be specified and it is possible to transmit data for only part of a frame, declaring the rest of the frame to be filled in by data from a previous frame, or left blank.

I'd like to transmit data for only part of the frame, but that data ought reference some other frame. I suggest (but am in no way married to) supporting t=z in this context to indicate that the argument to f= is a frame id. the geometry is interpreted the same way -- a destination within the working frame. i would personally be satisfied with selecting a source to overlap with the destination, but if you want to be able to move the source region to some dest, you'd need two coordinates for the source (if these are supported, but not provided, the source origin ought be assumed to match the dest origin IMHO).

so i would still only ever have two frames (and not 1+2, 1+3, 1+4 and so on, but 1+2 throughout). my rebuild operation would be wholly contained within the control block, referencing kitty-side data. my wipe operation would still be transmitted, but (a) i needn't keep state to generate 0s and (b) i can compress the hell out of a bunch of 0s. you needn't store anything that you're not already storing, and there's minimal churn in your own memories.

this operation effectively gets me O(1) time, O(1) state wipe+rebuild, and i try not to bug you for much, but that's too sweet not to go for =]. whaddya think?

Describe the solution you'd like
A clear and concise description of what you want to happen.

When sending an animation op with a=f, t=z means i wish to use a previous frame as the new animation data, rather than supplying it inline or via the filesystem etc. in this case, f=N will be understood to reference frame N, which must exist. two new params may or may not be added to specify the origin on the referenced frame; either way, in the absence of such a specification, the source region is chosen to overlap the destination region. invalid origin specification for either the source or dest is an error. t=z without f=N is either an error, or a default to frame 1.

It is undefined whether later cleanup of the referenced frame invalidates the derived frame (for my case, i'll only have two frames, so it shouldn't matter).

Describe alternatives you've considered
(1) Using mosaics (i.e. composing a larger graphic out of smaller ones), if granular to the cell level, there is no need for wiping nor restoring. I'd like to do this, but I've run into performance problems with all terminals with which I've tried it. I would need to keep the wipe+rebuild solution around, and I'd rather not have two paths. The animation protocol gets me almost all the way threre; this would effectively close the gap, while retaining one big graphic rather than hundreds.

(2) Using z-indices, there's less need for wipes-and-rebuilds, but they're sometimes still necessary if the image is not to be broken up (canonical example: partially transparent bitmap, some text underneath, some text atop, and all text has opaque backgrounds), and that decays to the mosaic case (I do intend to take advantage of z-indexing, as it's the only way to get text-above-graphic, but it's not a complete solution)

Even if there are other ways to get there, this seems a very low-cost (from a resources perspective -- I don't mean to presume it's insignificant work) addition; it seems to fit into the spec cleanly; it closes a conceptual hole in the protocol; this gets me mosaic-level capabilities without both of us having to track hundreds of cell-sized graphics.

Additional context

the power of j robert oppenheimer compels you!

330px-JROppenheimer-LosAlamos

@kovidgoyal
Copy link
Owner

Seems reasonable at first blush, I would want to be able to specify
different source and destination regions and type of composition
operation (replace, blend at least).

As for escape code design will look into that in detail later, but seems
cleaner to use a=c for ("compose" mode) where you can specify frame
composition operations, since no real data is being transmitted.

I'll get to it when I have some time, or if you are eager you can submit
a PR for me to review.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jul 7, 2021

Oh and while Oppenheimer certainly has a compelling visage as a lapsed theoretical physicist, I dont find him overly compelling :)

@dankamongmen
Copy link
Contributor Author

excellent, i'm glad to hear you find it plausible. you're on 0.21.2 now, right? when do you see 0.21.3 happening? if not for a minute, i might try to knock it out, but no promises. no rush, obviously. thanks!

@kovidgoyal
Copy link
Owner

There's no rush for 0.21.3 basically the only thing that needs a relative quick release is the synchronized update bug you reported, but since that bug has existed for years and no one ran into it until you did, its not that urgent.

@kovidgoyal
Copy link
Owner

I have implemented this in master. Please check that it meets your
requirements and works for you. I have added only the most rudimentary
of tests.

@dankamongmen
Copy link
Contributor Author

<3 outstanding. i'm excited about this, and will write code against it no later than this week's end, and probably tonight. i will have unit tests around a fairly complex instance of it, so that'll serve as a second-order check. i'll do a one-off build where Notcurses engages this behavior for all kitty > 0.20.0 to test that it works, but in reality we'll be conditional on version >= 0.21.3 -- does that sound reasonable?

and THANKS. with this change, the Kitty implementation of Notcurses will be lean and mean indeed, and fundamentally far out ahead of all other terminal bitmap implementations. you might have seen that i recently implemented deflate for the initial large transmission when using animation, and picked up a nice bandwidth win off that (once i thread frames out, it ought be an unconditional latency win for multiframe images as well).

@dankamongmen
Copy link
Contributor Author

dankamongmen/notcurses#1900 addresses this feature from my side.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jul 23, 2021 via email

@dankamongmen
Copy link
Contributor Author

alright, i've coded up an initial approach, and things aren't working as i expected. much too early to say whose bug it is, though. i'll continue to experiment, and give more useful results when i have them.

@kovidgoyal
Copy link
Owner

Cool, like I said, I haven't really tested this functionality, beyond
unit tests, so there could well be bugs.

@dankamongmen
Copy link
Contributor Author

I fixed some errors of mine and now it's pretty much working; I have one remaining issue, but I believe it too to be my bug. I'll know within a few hours max. Looking really good, though.

@dankamongmen
Copy link
Contributor Author

things seem to be working perfectly!

@kovidgoyal
Copy link
Owner

kovidgoyal commented Jul 26, 2021 via email

@dankamongmen
Copy link
Contributor Author

On Sun, Jul 25, 2021 at 06:26:55PM -0700, nick black wrote: things seem to be working perfectly!
Great, then it's ready for the next release.

yep, and i'll be supporting it out of the box. thanks!

@kovidgoyal
Copy link
Owner

Cool, note that the kitty version is 0.22.0 not 0.21.3 (there were too many changes pending for a point release).

@dankamongmen
Copy link
Contributor Author

i'll update to reflect that, thanks. it's possible that there's a bug when using composition on an image which has moved from its original position, but it might be my bug, just a heads-up. if it looks to be your issue, i'll of course file a new issue.

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

No branches or pull requests

2 participants