eazygit 0.5.1

A fast TUI for Git with staging, conflicts, rebase, and palette-first UX
Documentation
//! iTerm2 inline image protocol implementation.
//! 
//! iTerm2 supports displaying inline images using escape sequences.
//! Format: ESC ] 1337 ; File = [args] : base64_data BEL
//!
//! Requires the `background-images` feature to be enabled.

#[cfg(feature = "background-images")]
use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64};
#[cfg(feature = "background-images")]
use image::DynamicImage;
use std::io::Write;

pub struct ITerm2ImageRenderer;

impl ITerm2ImageRenderer {
    /// Render an image as an iTerm2 inline image.
    /// 
    /// Returns the escape sequence to display the image at full terminal resolution.
    #[cfg(feature = "background-images")]
    pub fn render_background(img: &DynamicImage, width_cells: u16, height_cells: u16) -> Result<String, String> {
        // Convert image to PNG for transmission
        let mut png_data = Vec::new();
        img.write_to(&mut std::io::Cursor::new(&mut png_data), image::ImageFormat::Png)
            .map_err(|e| format!("Failed to encode PNG: {}", e))?;
        
        // Base64 encode
        let b64 = BASE64.encode(&png_data);
        
        // iTerm2 inline image protocol:
        // ESC ] 1337 ; File = [arguments] : base64_data BEL
        // Arguments:
        //   width=N (cells or pixels with 'px' suffix)
        //   height=N (cells or pixels with 'px' suffix)
        //   preserveAspectRatio=0 (stretch to fit)
        //   inline=1 (display inline)
        
        let sequence = format!(
            "\x1b]1337;File=width={};height={};preserveAspectRatio=0;inline=1:{}\x07",
            width_cells,
            height_cells,
            b64
        );
        
        Ok(sequence)
    }
    
    /// Clear the screen to prepare for background rendering.
    pub fn clear_screen() -> String {
        "\x1b[2J\x1b[H".to_string()
    }
}

#[cfg(test)]
#[cfg(feature = "background-images")]
mod tests {
    use super::*;
    
    #[test]
    fn test_render_small_image() {
        // Create a tiny 2x2 image
        let img = image::DynamicImage::ImageRgb8(
            image::RgbImage::from_pixel(2, 2, image::Rgb([100, 150, 200]))
        );
        
        let result = ITerm2ImageRenderer::render_background(&img, 80, 24);
        assert!(result.is_ok());
        
        let sequence = result.unwrap();
        assert!(sequence.contains("\x1b]1337"));
        assert!(sequence.contains("width=80"));
        assert!(sequence.contains("height=24"));
    }
}