feat(image): add kitty chunked image transmission
Swadhin Biswas committed 7 months ago
60a9dd7
1 parent bdb703e
commit 60a9dd7
1 file changed
+50 -0
Showing 1 changed file+50-0
▼src/image_backend/mod.rs
+50-0
| @@ -98,3 +98,53 @@ fn extract_gif_frames(image_path: &str) -> Result<Vec<image::DynamicImage>, Stri | ||
98 | 98 | |
99 | 99 | match image::open(path) { |
100 | 100 | Ok(img) => { |
101 | + // For now, return single frame (first frame of GIF) | |
102 | + // Full animation support would require the 'gif' crate | |
103 | + Ok(vec![img]) | |
104 | + } | |
105 | + Err(e) => Err(format!("Failed to open GIF: {}", e)), | |
106 | + } | |
107 | +} | |
108 | + | |
109 | +/// Display a single image frame using kitty graphics protocol | |
110 | +fn display_kitty_frame( | |
111 | + img: &image::DynamicImage, | |
112 | + max_cols: usize, | |
113 | + max_rows: usize, | |
114 | +) -> Result<(usize, usize), String> { | |
115 | + // Calculate dimensions — fit within max_cols x max_rows | |
116 | + let (orig_w, orig_h) = (img.width() as f64, img.height() as f64); | |
117 | + let cell_w = 8.0_f64; | |
118 | + let cell_h = 16.0_f64; | |
119 | + | |
120 | + let max_px_w = max_cols as f64 * cell_w; | |
121 | + let max_px_h = max_rows as f64 * cell_h; | |
122 | + | |
123 | + let scale = (max_px_w / orig_w).min(max_px_h / orig_h).min(1.0); | |
124 | + let target_w = (orig_w * scale) as u32; | |
125 | + let target_h = (orig_h * scale) as u32; | |
126 | + | |
127 | + let resized = img.resize(target_w, target_h, image::imageops::FilterType::Lanczos3); | |
128 | + let rgba = resized.to_rgba8(); | |
129 | + let raw = rgba.as_raw(); | |
130 | + | |
131 | + let encoded = base64::engine::general_purpose::STANDARD.encode(raw); | |
132 | + let stdout = io::stdout(); | |
133 | + let mut out = stdout.lock(); | |
134 | + | |
135 | + let chunk_size = 4096; | |
136 | + let chunks: Vec<&str> = encoded | |
137 | + .as_bytes() | |
138 | + .chunks(chunk_size) | |
139 | + .map(|c| std::str::from_utf8(c).unwrap_or("")) | |
140 | + .collect(); | |
141 | + | |
142 | + for (i, chunk) in chunks.iter().enumerate() { | |
143 | + let more = if i < chunks.len() - 1 { 1 } else { 0 }; | |
144 | + if i == 0 { | |
145 | + write!( | |
146 | + out, | |
147 | + "\x1b_Ga=T,f=32,s={},v={},m={};{}\x1b\\", | |
148 | + target_w, target_h, more, chunk | |
149 | + ) | |
150 | + .ok(); | |
101 | 151 | |