From 22609e39c38dff029ce8db34682b0d82eeb41e28 Mon Sep 17 00:00:00 2001 From: mmb L <7960706+mammothb@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:10:43 +0800 Subject: [PATCH 1/2] feat: response config size options for popups --- lua/image/renderer.lua | 18 +++++++++++------- lua/image/utils/document.lua | 1 - 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lua/image/renderer.lua b/lua/image/renderer.lua index 6a921a1..8a190cb 100644 --- a/lua/image/renderer.lua +++ b/lua/image/renderer.lua @@ -43,8 +43,8 @@ local render = function(image) if not term_size then return end local scale_factor = 1.0 if type(state.options.scale_factor) == "number" then scale_factor = state.options.scale_factor end - local image_rows = math.floor(image.image_height / term_size.cell_height * scale_factor) - local image_columns = math.floor(image.image_width / term_size.cell_width * scale_factor) + local natural_image_rows = math.floor(image.image_height / term_size.cell_height) + local natural_image_columns = math.floor(image.image_width / term_size.cell_width) log.debug(("render() %s"):format(image.id), { id = image.id, @@ -72,20 +72,24 @@ local render = function(image) if width == 0 and height ~= 0 then width = math.ceil(geometry_height_px * aspect_ratio / term_size.cell_width) end if height == 0 and width ~= 0 then height = math.ceil(geometry_width_px / aspect_ratio / term_size.cell_height) end - -- if both w/h are missing, use the image dimensions + -- if both w/h are missing, use the natural image dimensions (unscaled) if width == 0 and height == 0 then - width = image_columns - height = image_rows + width = natural_image_columns + height = natural_image_rows end -- rendered size cannot be larger than the image itself - -- width = math.min(width, image_columns) - -- height = math.min(height, image_rows) + -- width = math.min(width, natural_image_columns) + -- height = math.min(height, natural_image_rows) -- screen max width/height width = math.min(width, term_size.screen_cols) -- height = math.min(height, term_size.screen_rows) + -- apply scale_factor to resolved geometry + width = math.max(1, math.floor(width * scale_factor)) + height = math.max(1, math.floor(height * scale_factor)) + log.debug(("(1) x: %d, y: %d, width: %d, height: %d"):format(original_x, original_y, width, height)) if image.window ~= nil then diff --git a/lua/image/utils/document.lua b/lua/image/utils/document.lua index 4d90ef4..24edafa 100644 --- a/lua/image/utils/document.lua +++ b/lua/image/utils/document.lua @@ -162,7 +162,6 @@ local create_document_integration = function(config) local win = vim.api.nvim_open_win(buf, false, win_config) popup_window = win - image.ignore_global_max_size = true image.window = win image.buffer = buf From 6899f52e9d56fd031099699b80753f571d48f5b9 Mon Sep 17 00:00:00 2001 From: mmb L <7960706+mammothb@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:17:09 +0800 Subject: [PATCH 2/2] feat: popup window matches final image size --- lua/image/renderer.lua | 17 ++++++++--------- lua/image/utils/document.lua | 29 ++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/lua/image/renderer.lua b/lua/image/renderer.lua index 8a190cb..0154495 100644 --- a/lua/image/renderer.lua +++ b/lua/image/renderer.lua @@ -45,6 +45,9 @@ local render = function(image) if type(state.options.scale_factor) == "number" then scale_factor = state.options.scale_factor end local natural_image_rows = math.floor(image.image_height / term_size.cell_height) local natural_image_columns = math.floor(image.image_width / term_size.cell_width) + -- scaled natural size: the image must never be rendered larger than this + local scaled_natural_width = math.max(1, math.floor(natural_image_columns * scale_factor)) + local scaled_natural_height = math.max(1, math.floor(natural_image_rows * scale_factor)) log.debug(("render() %s"):format(image.id), { id = image.id, @@ -72,24 +75,20 @@ local render = function(image) if width == 0 and height ~= 0 then width = math.ceil(geometry_height_px * aspect_ratio / term_size.cell_width) end if height == 0 and width ~= 0 then height = math.ceil(geometry_width_px / aspect_ratio / term_size.cell_height) end - -- if both w/h are missing, use the natural image dimensions (unscaled) + -- if both w/h are missing, use the scaled natural image dimensions if width == 0 and height == 0 then - width = natural_image_columns - height = natural_image_rows + width = scaled_natural_width + height = scaled_natural_height end -- rendered size cannot be larger than the image itself - -- width = math.min(width, natural_image_columns) - -- height = math.min(height, natural_image_rows) + width = math.min(width, scaled_natural_width) + height = math.min(height, scaled_natural_height) -- screen max width/height width = math.min(width, term_size.screen_cols) -- height = math.min(height, term_size.screen_rows) - -- apply scale_factor to resolved geometry - width = math.max(1, math.floor(width * scale_factor)) - height = math.max(1, math.floor(height * scale_factor)) - log.debug(("(1) x: %d, y: %d, width: %d, height: %d"):format(original_x, original_y, width, height)) if image.window ~= nil then diff --git a/lua/image/utils/document.lua b/lua/image/utils/document.lua index 24edafa..5939082 100644 --- a/lua/image/utils/document.lua +++ b/lua/image/utils/document.lua @@ -141,12 +141,34 @@ local create_document_integration = function(config) local term_size = utils.term.get_size() if not term_size then return end - local width, height = utils.math.adjust_to_aspect_ratio( + local state = image.global_state + local scale_factor = state.options.scale_factor or 1.0 + + -- compute the image's scaled natural width and apply same constraints as the renderer + local natural_width = math.max(1, math.floor(image.image_width / term_size.cell_width * scale_factor)) + local width = math.min(natural_width, math.floor(term_size.screen_cols / 2)) + if state.options.max_width then width = math.min(width, state.options.max_width) end + if state.options.max_width_window_percentage then + width = math.min(width, math.floor(term_size.screen_cols * state.options.max_width_window_percentage / 100)) + end + local height = 0 + width, height = utils.math.adjust_to_aspect_ratio( + term_size, + image.image_width, + image.image_height, + width, + height + ) + if state.options.max_height then height = math.min(height, state.options.max_height) end + if state.options.max_height_window_percentage then + height = math.min(height, math.floor(term_size.screen_rows * state.options.max_height_window_percentage / 100)) + end + width, height = utils.math.adjust_to_aspect_ratio( term_size, image.image_width, image.image_height, - math.floor(term_size.screen_cols / 2), - 0 + width, + height ) local win_config = { relative = "cursor", @@ -162,6 +184,7 @@ local create_document_integration = function(config) local win = vim.api.nvim_open_win(buf, false, win_config) popup_window = win + image.ignore_global_max_size = true image.window = win image.buffer = buf