From ad09fb89d9cb8216ab76b3c9d29a366e1d8198c5 Mon Sep 17 00:00:00 2001 From: ze0987 Date: Wed, 26 Mar 2025 14:10:14 +0100 Subject: [PATCH] perf!: faster image preview with optimized `magick` arguments (#2533) Co-authored-by: sxyazi --- yazi-config/preset/yazi-default.toml | 9 ++++-- yazi-plugin/preset/plugins/magick.lua | 35 ++++++++++---------- yazi-plugin/preset/plugins/svg.lua | 46 +++++++++++++++++++++++++++ yazi-plugin/src/loader/loader.rs | 1 + 4 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 yazi-plugin/preset/plugins/svg.lua diff --git a/yazi-config/preset/yazi-default.toml b/yazi-config/preset/yazi-default.toml index 1f6f2b8b..fe641dfa 100644 --- a/yazi-config/preset/yazi-default.toml +++ b/yazi-config/preset/yazi-default.toml @@ -98,7 +98,8 @@ spotters = [ { mime = "text/*", run = "code" }, { mime = "application/{mbox,javascript,wine-extension-ini}", run = "code" }, # Image - { mime = "image/{avif,hei?,jxl,svg+xml}", run = "magick" }, + { mime = "image/{avif,hei?,jxl}", run = "magick" }, + { mime = "image/svg+xml", run = "svg" }, { mime = "image/*", run = "image" }, # Video { mime = "video/*", run = "video" }, @@ -107,7 +108,8 @@ spotters = [ ] preloaders = [ # Image - { mime = "image/{avif,hei?,jxl,svg+xml}", run = "magick" }, + { mime = "image/{avif,hei?,jxl}", run = "magick" }, + { mime = "image/svg+xml", run = "svg" }, { mime = "image/*", run = "image" }, # Video { mime = "video/*", run = "video" }, @@ -125,7 +127,8 @@ previewers = [ # JSON { mime = "application/{json,ndjson}", run = "json" }, # Image - { mime = "image/{avif,hei?,jxl,svg+xml}", run = "magick" }, + { mime = "image/{avif,hei?,jxl}", run = "magick" }, + { mime = "image/svg+xml", run = "svg" }, { mime = "image/*", run = "image" }, # Video { mime = "video/*", run = "video" }, diff --git a/yazi-plugin/preset/plugins/magick.lua b/yazi-plugin/preset/plugins/magick.lua index 8524725e..a9496cdd 100644 --- a/yazi-plugin/preset/plugins/magick.lua +++ b/yazi-plugin/preset/plugins/magick.lua @@ -24,24 +24,19 @@ function M:preload(job) return true end - local cmd = Command("magick"):args { - "-density", - 200, - tostring(job.file.url), - "-flatten", - "-resize", - string.format("%dx%d^", rt.preview.max_width, rt.preview.max_height), - "-quality", - rt.preview.image_quality, - "-auto-orient", - "JPG:" .. tostring(cache), - } - - if rt.tasks.image_alloc > 0 then - cmd = cmd:env("MAGICK_MEMORY_LIMIT", rt.tasks.image_alloc) + local cmd = M.with_env() + if job.args.flatten then + cmd = cmd:arg("-flatten") end - local status, err = cmd:env("MAGICK_THREAD_LIMIT", 1):status() + -- stylua: ignore + local status, err = cmd:args { + tostring(job.file.url), "-auto-orient", "-strip", + "-sample", string.format("%dx%d>", rt.preview.max_width, rt.preview.max_height), + "-quality", rt.preview.image_quality, + string.format("JPG:%s", cache), + }:status() + if status then return status.success else @@ -51,4 +46,12 @@ end function M:spot(job) require("file"):spot(job) end +function M.with_env() + local cmd = Command("magick"):env("MAGICK_THREAD_LIMIT", 1) + if rt.tasks.image_alloc > 0 then + cmd = cmd:env("MAGICK_MEMORY_LIMIT", rt.tasks.image_alloc) + end + return cmd +end + return M diff --git a/yazi-plugin/preset/plugins/svg.lua b/yazi-plugin/preset/plugins/svg.lua new file mode 100644 index 00000000..aac9e127 --- /dev/null +++ b/yazi-plugin/preset/plugins/svg.lua @@ -0,0 +1,46 @@ +local M = {} + +function M:peek(job) + local start, cache = os.clock(), ya.file_cache(job) + if not cache then + return + end + + local ok, err = self:preload(job) + if not ok or err then + return + end + + ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock())) + ya.image_show(cache, job.area) + ya.preview_widgets(job, {}) +end + +function M:seek() end + +function M:preload(job) + local cache = ya.file_cache(job) + if not cache or fs.cha(cache) then + return true + end + + -- stylua: ignore + local cmd = require("magick").with_env():args { + "-density", 200, + tostring(job.file.url), "-strip", + "-resize", string.format("%dx%d^", rt.preview.max_width, rt.preview.max_height), + "-quality", rt.preview.image_quality, + string.format("JPG:%s", cache), + } + + local status, err = cmd:status() + if status then + return status.success + else + return true, Err("Failed to start `magick`, error: %s", err) + end +end + +function M:spot(job) require("file"):spot(job) end + +return M diff --git a/yazi-plugin/src/loader/loader.rs b/yazi-plugin/src/loader/loader.rs index 7caf4564..8869e97b 100644 --- a/yazi-plugin/src/loader/loader.rs +++ b/yazi-plugin/src/loader/loader.rs @@ -42,6 +42,7 @@ impl Default for Loader { ("noop".to_owned(), preset!("plugins/noop").into()), ("pdf".to_owned(), preset!("plugins/pdf").into()), ("session".to_owned(), preset!("plugins/session").into()), + ("svg".to_owned(), preset!("plugins/svg").into()), ("video".to_owned(), preset!("plugins/video").into()), ("zoxide".to_owned(), preset!("plugins/zoxide").into()), ]);