feat(image): implement sixel image backend

Swadhin Biswas committed 7 months ago
98b0928
1 parent 60a9dd7
commit 98b0928
1 file changed
+50 -0
Showing 1 changed file+50-0
▼src/image_backend/mod.rs
+50-0
148
148
target_w, target_h, more, chunk
149
149
)
150
150
.ok();
151
+ } else {
152
+ write!(out, "\x1b_Gm={};{}\x1b\\", more, chunk).ok();
153
+ }
154
+ }
155
+
156
+ let display_w = (target_w as f64 / cell_w).ceil() as usize;
157
+ let display_h = (target_h as f64 / cell_h).ceil() as usize;
158
+
159
+ Ok((display_w, display_h))
160
+}
161
+
162
+/// Display an image using the kitty graphics protocol.
163
+/// Returns the dimensions used.
164
+pub fn display_kitty(
165
+ image_path: &str,
166
+ max_cols: usize,
167
+ max_rows: usize,
168
+) -> Result<(usize, usize), String> {
169
+ let path = Path::new(image_path);
170
+ if !path.exists() {
171
+ return Err(format!("Image not found: {}", image_path));
172
+ }
173
+
174
+ // Check if it's an animated GIF
175
+ if let Ok(frames) = extract_gif_frames(image_path) {
176
+ if frames.len() > 1 {
177
+ // Display first frame for now (full animation support requires terminal refresh loop)
178
+ return display_kitty_frame(&frames[0], max_cols, max_rows);
179
+ }
180
+ }
181
+
182
+ let img = image::open(path).map_err(|e| format!("Failed to open image: {}", e))?;
183
+
184
+ // Calculate dimensions — fit within max_cols x max_rows
185
+ // Assume ~2:1 character aspect ratio (chars are taller than wide)
186
+ let (orig_w, orig_h) = (img.width() as f64, img.height() as f64);
187
+ let cell_w = 8.0_f64; // approximate pixel width of a terminal cell
188
+ let cell_h = 16.0_f64; // approximate pixel height of a terminal cell
189
+
190
+ let max_px_w = max_cols as f64 * cell_w;
191
+ let max_px_h = max_rows as f64 * cell_h;
192
+
193
+ let scale = (max_px_w / orig_w).min(max_px_h / orig_h).min(1.0);
194
+ let target_w = (orig_w * scale) as u32;
195
+ let target_h = (orig_h * scale) as u32;
196
+
197
+ let resized = img.resize(target_w, target_h, image::imageops::FilterType::Lanczos3);
198
+ let rgba = resized.to_rgba8();
199
+ let raw = rgba.as_raw();
200
+
151
201