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

Support kitty remote pixel transfer #10

Open
bogzbonny opened this issue Apr 5, 2023 · 2 comments
Open

Support kitty remote pixel transfer #10

bogzbonny opened this issue Apr 5, 2023 · 2 comments

Comments

@bogzbonny
Copy link

bogzbonny commented Apr 5, 2023

As far as I can tell pic currently has the best system for interfacing with kitty image protocol as it allows for handling of kitty image ids... hence it's my fav rust cui image viewing library!

One things that's missing is remote pixel transfer. This is cool for a few reasons, but I'm most interested in remote viewing such that temp-file artifacts aren't left around (also good for SSHing)

https://sw.kovidgoyal.net/kitty/graphics-protocol/#transferring-pixel-data

viuer implemented it reasonably well here https://github.com/atanunq/viuer/blob/master/src/printer/kitty.rs#L154

Here is snippet of some of my adapted code (which you're welcome to use in implementing this feature if you desire).

    pub fn render_new_img(
        &mut self, buf: &[u8], buf_width: u32, buf_height: u32, id: u32, cols: u16, rows: u16,
    ) -> bool {
        let encoded = general_purpose::STANDARD.encode(buf);

        let mut iter = encoded.chars().peekable();
        let first_chunk: String = iter.by_ref().take(4096).collect();

        // write the first chunk, which describes the image
        let first = format!(
            "{KITTY_START}f=24,a=T,t=d,i={},p=1,s={buf_width},v={buf_height},c={},r={},m=1,q=2;{first_chunk}{KITTY_END}",
            id, cols, rows,
        );
        self.images_queue.push((None, first));

        // write all the chunks, each containing 4096 bytes of data
        while iter.peek().is_some() {
            let chunk: String = iter.by_ref().take(4096).collect();
            let m = if iter.peek().is_some() { 1 } else { 0 };
            let next = format!("{KITTY_START}m={m};{chunk}{KITTY_END}");
            self.images_queue.push((None, next));
        }
    }
@emsquid
Copy link
Owner

emsquid commented Apr 5, 2023

Thanks for loving it!
I will try to see if I can implement that soon, I never thought about it but it shouldn't be that hard, I have been using it in some kitty tests. Great suggestion from you :)
I wonder how you think it should work, should it be an option? a default? how should I choose between sending files names and pixels ?

@bogzbonny
Copy link
Author

bogzbonny commented Apr 5, 2023

Oh yeah interesting question ... judging by your design so far, I'd recommend adding this feature as an option within your current Options struct. Also I'm looking at the options struct right now, and I'm thinking it may a bit more sense to group all your kitty options together under a common enum. For instance, is it not bad state if the user sets both the clear and load to Some(...)?

I'd personally probably do something like this:

pub struct Options {
  ..
  kitty_op: Option<KittyOp>,
}

pub enum KittyOp {
  Load(u32), 
  LoadRemote(u32),
  Display(u32),
  Clear(u32),
}

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

No branches or pull requests

2 participants