Fix aspect ratio when rendering images with kitty protocol

This commit is contained in:
Bryan Lee
2025-03-12 15:06:06 +08:00
parent 95daca616d
commit f091a69790
3 changed files with 43 additions and 10 deletions

View File

@@ -2032,13 +2032,16 @@ fn prepKittyPlacement(
break :offset_y @intCast(offset_pixels);
} else 0;
// Get the grid size that respects aspect ratio
const grid_size = p.gridSize(image.*, t);
// If we specify `rows` then our offset above is in viewport space
// and not in the coordinate space of the source image. Without `rows`
// that's one and the same.
const source_offset_y: u32 = if (p.rows > 0) source_offset_y: {
const source_offset_y: u32 = if (grid_size.rows > 0) source_offset_y: {
// Determine the scale factor to apply for this row height.
const image_height: f64 = @floatFromInt(image.height);
const viewport_height: f64 = @floatFromInt(p.rows * self.grid_metrics.cell_height);
const viewport_height: f64 = @floatFromInt(grid_size.rows * self.grid_metrics.cell_height);
const scale: f64 = image_height / viewport_height;
// Apply the scale to the offset
@@ -2071,11 +2074,11 @@ fn prepKittyPlacement(
image.height -| source_y;
// Calculate the width/height of our image.
const dest_width = if (p.columns > 0) p.columns * self.grid_metrics.cell_width else source_width;
const dest_height = if (p.rows > 0) rows: {
const dest_width = grid_size.cols * self.grid_metrics.cell_width;
const dest_height = if (grid_size.rows > 0) rows: {
// Clip to the viewport to handle scrolling. offset_y is already in
// viewport scale so we can subtract it directly.
break :rows (p.rows * self.grid_metrics.cell_height) - offset_y;
break :rows (grid_size.rows * self.grid_metrics.cell_height) - offset_y;
} else source_height;
// Accumulate the placement

View File

@@ -1073,13 +1073,16 @@ fn prepKittyPlacement(
break :offset_y @intCast(offset_pixels);
} else 0;
// Get the grid size that respects aspect ratio
const grid_size = p.gridSize(image.*, t);
// If we specify `rows` then our offset above is in viewport space
// and not in the coordinate space of the source image. Without `rows`
// that's one and the same.
const source_offset_y: u32 = if (p.rows > 0) source_offset_y: {
const source_offset_y: u32 = if (grid_size.rows > 0) source_offset_y: {
// Determine the scale factor to apply for this row height.
const image_height: f64 = @floatFromInt(image.height);
const viewport_height: f64 = @floatFromInt(p.rows * self.grid_metrics.cell_height);
const viewport_height: f64 = @floatFromInt(grid_size.rows * self.grid_metrics.cell_height);
const scale: f64 = image_height / viewport_height;
// Apply the scale to the offset
@@ -1112,11 +1115,11 @@ fn prepKittyPlacement(
image.height -| source_y;
// Calculate the width/height of our image.
const dest_width = if (p.columns > 0) p.columns * self.grid_metrics.cell_width else source_width;
const dest_height = if (p.rows > 0) rows: {
const dest_width = grid_size.cols * self.grid_metrics.cell_width;
const dest_height = if (grid_size.rows > 0) rows: {
// Clip to the viewport to handle scrolling. offset_y is already in
// viewport scale so we can subtract it directly.
break :rows (p.rows * self.grid_metrics.cell_height) - offset_y;
break :rows (grid_size.rows * self.grid_metrics.cell_height) - offset_y;
} else source_height;
// Accumulate the placement

View File

@@ -687,6 +687,33 @@ pub const ImageStorage = struct {
// Calculate our image size in grid cells
const width_f64: f64 = @floatFromInt(width_px);
const height_f64: f64 = @floatFromInt(height_px);
// If only columns is specified, calculate rows based on aspect ratio
if (self.columns > 0 and self.rows == 0) {
const cols_f64: f64 = @floatFromInt(self.columns);
const cols_px = cols_f64 * cell_width_f64;
const aspect_ratio = height_f64 / width_f64;
const rows_px = cols_px * aspect_ratio;
const rows_cells = rows_px / cell_height_f64;
return .{
.cols = self.columns,
.rows = @intFromFloat(@ceil(rows_cells)),
};
}
// If only rows is specified, calculate columns based on aspect ratio
if (self.rows > 0 and self.columns == 0) {
const rows_f64: f64 = @floatFromInt(self.rows);
const rows_px = rows_f64 * cell_height_f64;
const aspect_ratio = width_f64 / height_f64;
const cols_px = rows_px * aspect_ratio;
const cols_cells = cols_px / cell_width_f64;
return .{
.cols = @intFromFloat(@ceil(cols_cells)),
.rows = self.rows,
};
}
const width_cells: u32 = @intFromFloat(@ceil(width_f64 / cell_width_f64));
const height_cells: u32 = @intFromFloat(@ceil(height_f64 / cell_height_f64));