Created
January 15, 2026 02:21
-
-
Save llimllib/bbe113c1388d733cd15844ac0a9821d4 to your computer and use it in GitHub Desktop.
Claude Code session: fix image aspect ratio
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ▐▛███▜▌ Claude Code v2.1.7 | |
| ▝▜█████▛▘ Opus 4.5 · Claude Pro | |
| ▘▘ ▝▝ ~/code/mdriver/fix-image-aspect | |
| ❯ mdriver is stretching images vertically when it displays them instead of | |
| keeping them in their proper aspect ratio | |
| ⏺ Let me explore how images are currently handled in the codebase. | |
| ⏺ Search(pattern: "image|Image", path: "~/code/mdriver/fix-image-aspect") | |
| ⎿ Found 9 files (ctrl+o to expand) | |
| ⏺ Search(pattern: "image|Image", path: "src/lib.rs", output_mode: "content") | |
| ⎿ Found 72 lines (ctrl+o to expand) | |
| ⏺ Read(src/lib.rs) | |
| ⎿ Read 80 lines | |
| ⏺ I see the issue. The calculation assumes terminal cells have a 2:1 height-to-width pixel ratio, but this may not match real terminals. Let me look at what typical values should be and check if there are any tests for image rendering. | |
| ⏺ Search(pattern: "PIXELS_PER|aspect|cell", path: "src/lib.rs", output_mode: | |
| "content") | |
| ⎿ Found 48 lines (ctrl+o to expand) | |
| ⏺ Let me search for any recent commits or changes related to image handling. | |
| ⏺ Bash(git log --oneline --all -20) | |
| ⎿ 0ccae1d fix: prevent image markdown from being broken by line wrapping | |
| (#16) | |
| c8e1499 fix: use configured width for horizontal rules instead of termi | |
| … +23 lines (ctrl+o to expand) | |
| ⏺ Bash(git show db84adf --stat) | |
| ⎿ commit db84adfcefbfc8182699584cc33527713e14aaeb | |
| Author: Bill Mill <[email protected]> | |
| Date: Wed Jan 14 11:42:57 2026 -0500 | |
| … +29 lines (ctrl+o to expand) | |
| ⏺ Bash(git show db84adf -- src/lib.rs | head -150) | |
| ⎿ commit db84adfcefbfc8182699584cc33527713e14aaeb | |
| Author: Bill Mill <[email protected]> | |
| Date: Wed Jan 14 11:42:57 2026 -0500 | |
| … +176 lines (ctrl+o to expand) | |
| ⏺ Let me look at any unit tests related to image rendering to understand expected behavior. | |
| ⏺ Search(pattern: "process_image|render_kitty|display_rows|display_cols", path: | |
| "tests", output_mode: "content") | |
| ⎿ Found 0 lines | |
| ⏺ Let me trace through the actual math with a concrete example to understand the issue better. | |
| ⏺ Read(src/lib.rs) | |
| ⎿ Read 45 lines | |
| ⏺ I see the issue. The code assumes terminal cells are exactly 2:1 (height:width in pixels), but this varies by terminal and font. Looking at the Kitty graphics protocol documentation, if we only specify c (columns) without r, Kitty will automatically calculate the correct row count to maintain aspect ratio. | |
| Let me fix this by removing the manual row calculation and letting Kitty handle it. | |
| ⏺ Update(src/lib.rs) | |
| ⎿ Removed 5 lines | |
| 2010 // Use the smaller of natural size or configured | |
| max width | |
| 2011 let display_cols = natural_cols.min(self.width); | |
| 2012 | |
| 2013 - // Calculate rows to maintain aspect ratio | |
| 2014 - // Terminal cells are roughly 2:1 (height:width in | |
| -pixels) | |
| 2015 - let aspect_ratio = img.height() as f64 / | |
| -img.width() as f64; | |
| 2016 - let display_rows = ((display_cols as f64) * | |
| -aspect_ratio / 2.0).ceil() as usize; | |
| 2017 - | |
| 2013 // Resize large images to reduce transfer size (cap | |
| at 2000px width) | |
| 2014 // but let kitty handle the display scaling | |
| 2015 let max_transfer_width = 2000u32; | |
| ⏺ Update(src/lib.rs) | |
| ⎿ Added 3 lines, removed 2 lines | |
| 2027 let mut png_data = Vec::new(); | |
| 2028 resized.write_to(&mut Cursor::new(&mut png_data), | |
| image::ImageFormat::Png)?; | |
| 2029 | |
| 2030 - // Render using kitty protocol with display size in | |
| -terminal cells | |
| 2031 - Ok(self.render_kitty_image(&png_data, display_cols, | |
| - display_rows)) | |
| 2030 + // Render using kitty protocol with display width in | |
| +columns | |
| 2031 + // Kitty will automatically calculate the row count | |
| + to maintain aspect ratio | |
| 2032 + Ok(self.render_kitty_image(&png_data, | |
| +display_cols)) | |
| 2033 } | |
| 2034 | |
| 2035 fn render_kitty_image(&self, png_data: &[u8], columns: | |
| usize, rows: usize) -> String { | |
| ⏺ Update(src/lib.rs) | |
| ⎿ Added 5 lines, removed 5 lines | |
| 2032 Ok(self.render_kitty_image(&png_data, | |
| display_cols)) | |
| 2033 } | |
| 2034 | |
| 2035 - fn render_kitty_image(&self, png_data: &[u8], columns: | |
| -usize, rows: usize) -> String { | |
| 2035 + fn render_kitty_image(&self, png_data: &[u8], columns: | |
| +usize) -> String { | |
| 2036 use base64::{engine::general_purpose::STANDARD, | |
| Engine as _}; | |
| 2037 | |
| 2038 let encoded = STANDARD.encode(png_data); | |
| ... | |
| 2050 let m = if is_last { 0 } else { 1 }; | |
| 2051 | |
| 2052 if i == 0 { | |
| 2053 - // First chunk: include format, transmission | |
| -parameters, and display size | |
| 2054 - // c=columns, r=rows tells kitty to scale | |
| -the image to fit in that many cells | |
| 2053 + // First chunk: include format, transmission | |
| +parameters, and display width | |
| 2054 + // c=columns tells kitty the width; it | |
| +calculates rows to maintain aspect ratio | |
| 2055 output.push_str(&format!( | |
| 2056 - "\x1b_Gf=100,a=T,c={},r={}, | |
| -m={};{}\x1b\\", | |
| 2057 - columns, rows, m, chunk | |
| 2056 + "\x1b_Gf=100,a=T,c={},m={};{}\x1b\\", | |
| 2057 + columns, m, chunk | |
| 2058 )); | |
| 2059 } else { | |
| 2060 // Continuation chunks | |
| ⏺ Now let me run the build and tests to ensure everything compiles and works correctly. | |
| ⏺ Bash(cargo fmt && cargo build 2>&1) | |
| ⎿ Updating crates.io index | |
| Locking 202 packages to latest compatible versions | |
| Adding toml v0.8.23 (available: v0.9.11+spec-1.1.0) | |
| … +169 lines (ctrl+o to expand) | |
| ⏺ Bash(cargo clippy --all-targets --all-features -- -D warnings 2>&1) | |
| ⎿ Checking stable_deref_trait v1.2.1 | |
| Checking cfg-if v1.0.4 | |
| Checking memchr v2.7.6 | |
| … +138 lines (ctrl+o to expand) | |
| ⏺ Bash(cargo test 2>&1) | |
| ⎿ Compiling serde v1.0.228 | |
| Compiling winnow v0.7.14 | |
| Compiling toml_write v0.1.2 | |
| … +161 lines (ctrl+o to expand) | |
| ⏺ The fix is complete. The issue was that the code was manually calculating the number of rows for image display by assuming terminal cells have exactly a 2:1 height-to-width pixel ratio. This assumption doesn't hold for all terminals and fonts, causing aspect ratio distortion. | |
| The fix removes the manual row calculation and instead only specifies the column count (c) in the Kitty graphics protocol. According to the Kitty documentation, when only c is specified without r, Kitty automatically calculates the correct number of rows to maintain the image's original aspect ratio based on the actual cell dimensions of the terminal. | |
| Changes made in src/lib.rs: | |
| 1. Removed the row calculation logic (lines 2013-2016 that calculated display_rows using the assumed 2:1 ratio) | |
| 2. Updated render_kitty_image to only take columns parameter instead of columns, rows | |
| 3. Changed the Kitty escape sequence from c={},r={},m={} to just c={},m={}, letting Kitty determine the correct row count | |
| This approach is more robust because Kitty knows the actual cell dimensions of the terminal and can calculate the correct aspect ratio regardless of the user's font or terminal configuration. | |
| ✻ Baked for 4m 18s | |
| ❯ much better! commit it | |
| ⏺ Bash(git status) | |
| ⎿ On branch fix-image-aspect | |
| Changes not staged for commit: | |
| (use "git add <file>..." to update what will be committed) | |
| … +4 lines (ctrl+o to expand) | |
| ⏺ Bash(git diff) | |
| ⎿ diff --git i/src/lib.rs w/src/lib.rs | |
| index 503f8f7..0bfb6b3 100644 | |
| --- i/src/lib.rs | |
| … +57 lines (ctrl+o to expand) | |
| ⏺ Bash(git log --oneline -5) | |
| ⎿ 0ccae1d fix: prevent image markdown from being broken by line wrapping | |
| (#16) | |
| c8e1499 fix: use configured width for horizontal rules instead of termi | |
| … +5 lines (ctrl+o to expand) | |
| ⏺ Bash(git add src/lib.rs && git commit -m "fix: preserve image aspect ratio by | |
| letting Kitty calculate row count…) | |
| ⎿ [fix-image-aspect 322bde5] fix: preserve image aspect ratio by letting | |
| Kitty calculate row count | |
| 1 file changed, 8 insertions(+), 12 deletions(-) | |
| ⏺ Bash(git status) | |
| ⎿ On branch fix-image-aspect | |
| nothing to commit, working tree clean | |
| ⏺ Done. Committed as 322bde5. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment