From b2ac03f352958c009534b5c6b9f12b3a9c51793a Mon Sep 17 00:00:00 2001 From: 3rd <3rd@users.noreply.github.com> Date: Mon, 17 Jul 2023 10:29:55 +0300 Subject: [PATCH] fix: prevent unnecessary rerenders and recrop previous images on new splits --- lua/image/backends/kitty/init.lua | 1 + lua/image/image.lua | 4 +- lua/image/renderer.lua | 82 ++++++++++++++++++------------- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/lua/image/backends/kitty/init.lua b/lua/image/backends/kitty/init.lua index f6e6b5b..e65e459 100644 --- a/lua/image/backends/kitty/init.lua +++ b/lua/image/backends/kitty/init.lua @@ -143,6 +143,7 @@ backend.render = function(image, x, y, width, height) helpers.restore_cursor() -- utils.debug("[kitty] rendered image", image.id, "(" .. image.internal_id .. ")") + -- utils.debug("path:", image.cropped_path, display_payload) end backend.clear = function(image_id, shallow) diff --git a/lua/image/image.lua b/lua/image/image.lua index 94775cf..77407c5 100644 --- a/lua/image/image.lua +++ b/lua/image/image.lua @@ -30,10 +30,10 @@ end function Image:render(geometry) if geometry then self.geometry = vim.tbl_deep_extend("force", self.geometry, geometry) end - -- utils.debug(("\n\n---------------- %s ----------------"):format(self.id)) + -- utils.debug(("---------------- %s ----------------"):format(self.id)) local was_rendered = renderer.render(self) - -- utils.debug(("[image] render: %s, success: %s x: %s, y: %s, width: %s, height: %s"):format( self.id, was_rendered, self.geometry.x, self.geometry.y, self.geometry.width, self.geometry.height)) + -- utils.debug( ("[image] render: %s, success: %s x: %s, y: %s, width: %s, height: %s"):format( self.id, was_rendered, self.geometry.x, self.geometry.y, self.geometry.width, self.geometry.height)) -- clear if render was prevented if self.is_rendered and not was_rendered then self.global_state.backend.clear(self.id, true) end diff --git a/lua/image/renderer.lua b/lua/image/renderer.lua index d9b6a98..8dbb7c8 100644 --- a/lua/image/renderer.lua +++ b/lua/image/renderer.lua @@ -278,15 +278,6 @@ local render = function(image) -- compute final geometry and prevent useless rerendering local rendered_geometry = { x = absolute_x, y = absolute_y, width = width, height = height } - -- if - -- image.is_rendered - -- and image.rendered_geometry.x == rendered_geometry.x - -- and image.rendered_geometry.y == rendered_geometry.y - -- and image.rendered_geometry.width == rendered_geometry.width - -- and image.rendered_geometry.height == rendered_geometry.height - -- then - -- return true - -- end -- handle crop/resize local pixel_width = width * term_size.cell_width @@ -295,23 +286,23 @@ local render = function(image) local cropped_pixel_height = height * term_size.cell_height local needs_crop = false local needs_resize = false + local initial_crop_hash = image.crop_hash + local initial_resize_hash = image.resize_hash -- compute crop top/bottom - if not state.backend.features.crop then - -- crop top - if absolute_y < bounds.top then - local visible_rows = height - (bounds.top - absolute_y) - cropped_pixel_height = visible_rows * term_size.cell_height - crop_offset_top = (bounds.top - absolute_y) * term_size.cell_height - absolute_y = bounds.top - needs_crop = true - end + -- crop top + if absolute_y < bounds.top then + local visible_rows = height - (bounds.top - absolute_y) + cropped_pixel_height = visible_rows * term_size.cell_height + crop_offset_top = (bounds.top - absolute_y) * term_size.cell_height + if not state.backend.features.crop then absolute_y = bounds.top end + needs_crop = true + end - -- crop bottom - if absolute_y + height > bounds.bottom then - cropped_pixel_height = (bounds.bottom - absolute_y + 1) * term_size.cell_height - needs_crop = true - end + -- crop bottom + if absolute_y + height > bounds.bottom then + cropped_pixel_height = (bounds.bottom - absolute_y + 1) * term_size.cell_height + needs_crop = true end -- compute resize @@ -343,19 +334,20 @@ local render = function(image) end -- crop + local crop_hash = ("%d-%d-%d-%d"):format(0, crop_offset_top, pixel_width, cropped_pixel_height) if needs_crop then - local crop_hash = ("%d-%d-%d-%d"):format(0, crop_offset_top, pixel_width, cropped_pixel_height) if (needs_resize and image.resize_hash ~= resize_hash) or image.crop_hash ~= crop_hash then - local cropped_image = magick.load_image(image.resized_path or image.path) - cropped_image:set_format("png") - - -- utils.debug(("cropping image %s to %dx%d"):format(image.path, pixel_width, cropped_pixel_height)) - cropped_image:crop(pixel_width, cropped_pixel_height, 0, crop_offset_top) - local tmp_path = state.tmp_dir .. "/" .. utils.base64.encode(image.id) .. "-cropped.png" - cropped_image:write(tmp_path) - cropped_image:destroy() - - image.cropped_path = tmp_path + if not state.backend.features.crop then + local cropped_image = magick.load_image(image.resized_path or image.path) + cropped_image:set_format("png") + + -- utils.debug(("cropping image %s to %dx%d"):format(image.path, pixel_width, cropped_pixel_height)) + cropped_image:crop(pixel_width, cropped_pixel_height, 0, crop_offset_top) + local tmp_path = state.tmp_dir .. "/" .. utils.base64.encode(image.id) .. "-cropped.png" + cropped_image:write(tmp_path) + cropped_image:destroy() + image.cropped_path = tmp_path + end image.crop_hash = crop_hash end else @@ -363,6 +355,28 @@ local render = function(image) image.crop_hash = nil end + if + image.is_rendered + and image.rendered_geometry.x == rendered_geometry.x + and image.rendered_geometry.y == rendered_geometry.y + and image.rendered_geometry.width == rendered_geometry.width + and image.rendered_geometry.height == rendered_geometry.height + and image.crop_hash == initial_crop_hash + and image.resize_hash == initial_resize_hash + then + -- utils.debug("skipping render", image.id) + return true + end + + -- utils.debug("redering to backend", image.id, { + -- x = absolute_x, + -- y = absolute_y, + -- width = width, + -- height = height, + -- resize_hash = image.resize_hash, + -- crop_hash = image.crop_hash, + -- }) + image.bounds = bounds state.backend.render(image, absolute_x, absolute_y, width, height) image.rendered_geometry = rendered_geometry