Skip to content

Commit

Permalink
fix: prevent unnecessary rerenders and recrop previous images on new …
Browse files Browse the repository at this point in the history
…splits
  • Loading branch information
3rd committed Jul 17, 2023
1 parent 9cbe8ea commit b2ac03f
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 36 deletions.
1 change: 1 addition & 0 deletions lua/image/backends/kitty/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions lua/image/image.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
82 changes: 48 additions & 34 deletions lua/image/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -343,26 +334,49 @@ 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
image.cropped_path = image.resized_path
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
Expand Down

0 comments on commit b2ac03f

Please sign in to comment.