Skip to content

Commit

Permalink
feat: extract cropping into renderer and handle with magick
Browse files Browse the repository at this point in the history
  • Loading branch information
3rd committed Jul 3, 2023
1 parent 2c1e1a6 commit 573e057
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 45 deletions.
51 changes: 7 additions & 44 deletions lua/image/backends/kitty/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,11 @@ end

-- extend from empty line strategy to use extmarks
backend.render = function(image, x, y, width, height)
local term_size = utils.term.get_size()
local with_virtual_placeholders = backend.state.options.kitty_method == "unicode-placeholders"

-- save cursor
helpers.move_cursor(x + 1, y + 1, true)

-- clear out of bounds images
if
y + height < image.bounds.top
or y > image.bounds.bottom
or x + width < image.bounds.left
or x > image.bounds.right
then
-- utils.debug( "deleting out of bounds image", { id = image.id, x = x, y = y, width = width, height = height, bounds = image.bounds })
helpers.write_graphics({
action = codes.control.action.delete,
display_delete = "i",
image_id = image.internal_id,
quiet = 2,
})
image.is_rendered = false
backend.state.images[image.id] = image
helpers.restore_cursor()
return
end
-- utils.debug("kitty: rendering image" .. image.path, { id = image.id, x = x, y = y, width = width, height = height, bounds = image.bounds })

-- transmit image
helpers.write_graphics({
action = codes.control.action.transmit,
Expand Down Expand Up @@ -93,33 +71,11 @@ backend.render = function(image, x, y, width, height)
return
end

-- default display
local pixel_width = width * term_size.cell_width
local pixel_height = height * term_size.cell_height
local pixel_top = 0

-- top crop
if y < image.bounds.top then
local visible_rows = height - (image.bounds.top - y)
pixel_height = visible_rows * term_size.cell_height
pixel_top = (image.bounds.top - y) * term_size.cell_height
y = image.bounds.top
end

-- bottom crop
if y + height > image.bounds.bottom then
--
pixel_height = (image.bounds.bottom - y + 1) * term_size.cell_height
end

helpers.move_cursor(x + 1, y + 1, false, backend.state.options.kitty_tmux_write_delay)
helpers.write_graphics({
action = codes.control.action.display,
quiet = 2,
image_id = image.internal_id,
display_width = pixel_width,
display_height = pixel_height,
display_y = pixel_top,
display_zindex = -1,
display_cursor_policy = codes.control.display_cursor_policy.do_not_move,
placement_id = image.internal_id,
Expand All @@ -130,6 +86,9 @@ backend.render = function(image, x, y, width, height)
end

backend.clear = function(image_id, shallow)
helpers.move_cursor(0, 0, true)

-- one
if image_id then
local image = backend.state.images[image_id]
if not image then return end
Expand All @@ -141,8 +100,11 @@ backend.clear = function(image_id, shallow)
})
image.is_rendered = false
if not shallow then backend.state.images[image_id] = nil end
helpers.restore_cursor()
return
end

--all
helpers.write_graphics({
action = codes.control.action.delete,
display_delete = "a",
Expand All @@ -152,6 +114,7 @@ backend.clear = function(image_id, shallow)
image.is_rendered = false
if not shallow then backend.state.images[id] = nil end
end
helpers.restore_cursor()
end

return backend
7 changes: 7 additions & 0 deletions lua/image/backends/ueberzug.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ local backend = {
---@diagnostic disable-next-line: assign-type-mismatch
state = nil,
}

backend.setup = function(state)
backend.state = state
if not child then spawn() end
end

backend.render = function(image, x, y, width, height)
if not child then return end
child.write({
Expand All @@ -77,8 +79,11 @@ backend.render = function(image, x, y, width, height)
image.is_rendered = true
backend.state.images[image.id] = image
end

backend.clear = function(image_id, shallow)
if not child then return end

-- one
if image_id then
local image = backend.state.images[image_id]
if not image then return end
Expand All @@ -90,6 +95,8 @@ backend.clear = function(image_id, shallow)
if not shallow then backend.state.images[image_id] = nil end
return
end

-- all
for id, image in pairs(backend.state.images) do
child.write({
action = "remove",
Expand Down
57 changes: 56 additions & 1 deletion lua/image/renderer.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local utils = require("image/utils")
local magick = require("image.magick")

---@return { x: number, y: number }
local get_global_offsets = function()
Expand Down Expand Up @@ -222,6 +223,50 @@ local render = function(image, state)
if prevent_rendering then absolute_y = -999999 end

image.bounds = bounds

-- clear out of bounds images
if
absolute_y + height < image.bounds.top
or absolute_y > image.bounds.bottom
or absolute_x + width < image.bounds.left
or absolute_x > image.bounds.right
then
if image.is_rendered then
-- utils.debug("deleting out of bounds image", { id = image.id, x = x, y = y, width = width, height = height, bounds = image.bounds })
state.backend.clear(image.id, true)
else
state.images[image.id] = image
end
return true
end

-- crop
local pixel_width = width * term_size.cell_width
local pixel_height = height * term_size.cell_height
local crop_offset_top = 0
local needs_crop = false

-- crop top
if absolute_y < image.bounds.top then
local visible_rows = height - (image.bounds.top - absolute_y)
pixel_height = visible_rows * term_size.cell_height
crop_offset_top = (image.bounds.top - absolute_y) * term_size.cell_height
absolute_y = image.bounds.top
needs_crop = true
end

-- crop bottom
if absolute_y > image.bounds.bottom then
pixel_height = (image.bounds.bottom - absolute_y + 1) * term_size.cell_height
needs_crop = true
end

-- crop right
if absolute_x + pixel_width > image.bounds.right then
pixel_width = (image.bounds.right - absolute_x) * term_size.cell_width
needs_crop = true
end

local rendered_geometry = { x = absolute_x, y = absolute_y, width = width, height = height }

-- prevent useless rerendering
Expand All @@ -235,8 +280,18 @@ local render = function(image, state)
return true
end

-- utils.debug(("(5) x: %d, y: %d, width: %d, height: %d y_offset: %d"):format(x, y, width, height, y_offset))
-- perform crop
if needs_crop then
local cropped_image = magick.load_image(image.original_path)
cropped_image:set_format("png")
utils.debug(("cropping image: %d, %d, %d, %d"):format(pixel_width, pixel_height, 0, crop_offset_top))
cropped_image:crop(pixel_width, pixel_height, 0, crop_offset_top)
local tmp_path = os.tmpname() .. ".png"
cropped_image:write(tmp_path)
image.path = tmp_path
end

-- utils.debug(("(5) x: %d, y: %d, width: %d, height: %d y_offset: %d"):format(x, y, width, height, y_offset))
state.backend.render(image, absolute_x, absolute_y, width, height)
image.rendered_geometry = rendered_geometry

Expand Down

0 comments on commit 573e057

Please sign in to comment.