11 个版本 (4 个破坏性更新)
0.4.0 | 2024 年 5 月 5 日 |
---|---|
0.2.0 | 2023 年 12 月 17 日 |
0.1.0 | 2023 年 10 月 23 日 |
0.0.5 | 2023 年 6 月 26 日 |
0.0.1 | 2022 年 7 月 20 日 |
#127 in 图像
每月 538 次下载
690KB
2.5K SLoC
所有脚趾
通过使用 freedesktop-specified 缩略图数据库(也称为 XDG 标准)提供缩略图。
缩略图通过一个共同的缓存与其他程序共享。
只有在尚未创建缩略图或原始文件已更改时,才会创建缩略图。
所有脚趾可以为许多图像格式创建缩略图。(参见“解码”支持的 image crate。)
此外,所有脚趾还可以使用其他程序创建其他类型文件的缩略图,以创建基本图像。(参见 Provider 部分。)
所有脚趾既是用于 shell 和脚本的交互式程序,也是 Rust 库。在代码或结构化数据中简称为“AMT”(或“amt”)。
[[目录]]
用法
使用文件作为参数调用 allmytoes
。程序会将缩略图的路径打印到 stdout
。
> allmytoes some_image.jpg
/home/me/.cache/thumbnails/large/b7931d1d6e0439c1a6e2e6b02c5b21a6.png
如果缩略图已经存在,所有脚趾将仅返回现有缩略图文件的路径。如果不存在,所有脚趾将首先创建图像的缩略图。
缩略图大小
最新的 freedesktop.org 规范(0.9.0)定义了四种不同的缩略图大小:普通、大、超大和超超大,最大边长分别为 128 像素、256 像素、512 像素和 1024 像素。
默认情况下,所有脚趾返回 大(256 像素)缩略图的路径。可以通过使用 -s
(--size
)选项并给出一个值来选择要返回的大小,该值从 {n
,l
,x
,xx
} 中选择。
例如,要获取一个超超大缩略图,调用方式如下
> allmytoes -sxx some_image.jpg
/home/me/.cache/thumbnails/xx-large/ad0779df58de36f038bdc4040a322bfe.png
小输入图像
如果输入图像小于请求的缩略图大小,缩略图将具有与输入图像相同的尺寸。缩略图永远不会比原始图像更大。
如果请求的大小还没有缩略图,AllMyToes将检查输入图像是否小于请求的缩略图大小。如果是这样,AllMyToes将确定覆盖输入图像尺寸的最小缩略图大小(大于或等于输入图像)。如果这个“可行”的缩略图大小与请求的缩略图大小不同,AllMyToes将使用这个更小的、“可行”的缩略图大小从头开始工作。AllMyToes这样做是为了避免为小图像创建不必要的、重复的缩略图。
这意味着对于小的输入图像,返回的缩略图路径可能不会对应于请求的缩略图大小,因为创建和保留(较大)请求大小的缩略图将浪费计算时间和磁盘空间。
如果出于某种原因必须获取请求大小的缩略图的路径,可以使用-F
(--force-size
)选项。但是,只有当有真正充分的理由时才这样做。
显示详细信息
使用--extensive
(或-e
)选项调用AllMyToes会在打印缩略图路径之外打印更多信息。提供的信息包括:
- 缩略图的路径
- 用于XDG缩略图名称的输入文件的URI散列
- 存储在缩略图中的所有元数据(键值对),作为“tEXt”条目
这无关紧要,无论是缩略图已经存在还是刚刚由AllMyToes创建。
所有数据都按键值对列表打印,每个元组一行。键与值之间用“:
”分隔。显示缩略图文件元数据的键值对前面有冒号,并按字母顺序打印。
示例
$ allmytoes --extensive some_image.jpg
Thumb path: /home/dude/.cache/thumbnails/large/c000276b8378a33e16e3fac005eebc02.png
Thumb hash: c000276b8378a33e16e3fac005eebc02
:Software: allmytoes
:Software::Version: 0.1.0
:Thumb::Image::Dimensions: 4608x3456
:Thumb::Image::Height: 3456
:Thumb::Image::Reorientation: Rotated 180 degrees, not flipped
:Thumb::Image::Width: 4608
:Thumb::MTime: 1693737198
:Thumb::Mimetype: image/jpeg
:Thumb::Size: 7777807
:Thumb::URI: file:///path/to/some_image.jpg
缩略图中可用的元数据当然取决于创建缩略图的软件。因此,以冒号(:
)开头的行可能会有所不同。
日志记录
默认情况下,AllMyToes会将警告和错误打印到stderr
。可以通过环境变量RUST_LOG
设置不同的日志级别。例如,做
export RUST_LOG=trace
以获取所有日志条目,直到最详细的“跟踪”级别。
提供者
如果定义了“提供者”,AllMyToes可以为非图像文件创建缩略图。提供者是一个shell命令或脚本来为特定的一组MIME类型提供图像。
AllMyToes支持一些文件格式
格式 | 依赖关系 |
---|---|
(evince-thumbnailer 或magick )和(exiftool 或pdfinfo 或gs ) |
|
Postscript | (evince-thumbnailer 或magick )和(exiftool 或gs ) |
SVG | inkscape 或magick |
各种视频格式 | ffmpeg (可选ffprobe & magick & bc 用于更复杂的缩略图)和(ffprobe 或(mediainfo 和bc )或(exiftool 和bc )) |
确切的MIME类型和提供者定义可以在/conf/provider.yaml
中找到。
定义提供者
用户可以在YAML文件中使用自己的提供者配置以添加对更多MIME类型的支持或实现更复杂的缩略图。
要这样做,请将 /conf/provider.yaml
复制到 ~/.config/allmytoes/provider.yaml
(如果 $XDG_CONFIG_HOME
已定义,则也可以使用 $XDG_CONFIG_HOME
)并对其进行修改。您还可以使用 -p
(--provider-config-file
)选项显式选择其他提供者配置。
❗请注意,提供者功能相对较新,在稳定之前,提供者配置的格式可能会发生变化。
提供者配置YAML文件在顶层包含一个字典列表。每个列表条目定义了一个提供者,用于一种或多种MIME类型。对于每个条目,有两个必需键和两个可选键。
键 | 必需 | 简短描述 |
---|---|---|
mimes |
是 | 列表,包含由提供者定义处理的MIME类型 |
commands |
是 | 列表,提供缩略图的命令,从上到下处理,直到成功为止 |
meta |
否 | 字典,将缩略图元数据键映射到提供它们的命令列表 |
revision |
否 | 用于跟踪提供者定义版本的整数 |
键 mimes
MIME类型列表定义了提供者将执行哪些MIME类型。MIME类型指定为 <type>/<subtype>
,例如 video/x-matroska
。如果为无法找到提供者的文件调用AllMyToes,则将在错误消息中打印MIME类型。找到提供者的MIME类型将在调试消息中打印,并在缩略图本身中作为元数据标记。 (如果您使用 --extensive
(-e
)选项,则可以查看。)
键 commmands
每个提供者条目必须有一个命令列表。命令是shell命令(或脚本),它们接受输入文件并将图像返回给AllMyToes。AllMyToes接受该图像并从中创建符合XDG规范的缩略图。命令通过将其复制到定义的位置来提供该图像。
当 mimes
列表中的某个MIME类型与输入文件匹配时,AllMyToes将执行 commands
列表中的第一个命令。如果该命令成功(退出代码 0
),AllMyToes将停止并使用该命令提供的缩略图。
如果命令未成功(退出代码 ≠ 0
),AllMyToes将尝试下一个命令,依此类推。
这允许使用不同的程序来提供缩略图。如果用户没有使用第一个命令的程序,另一个计算缩略图的方法可能有效。如果命令返回 0
但仍不提供有效的缩略图,AllMyToes将返回错误。
命令通过将其复制到临时目录中的某个路径来提供缩略图,该路径随后将被AllMyToes删除。
命令需要某些信息才能完成其工作,例如输入文件和将缩略图复制到的路径。因此,命令可以使用某些变量。
变量 | 内容 |
---|---|
%(file)s |
输入文件的完整路径 |
%(size)s |
理想情况下较长边应具有的像素大小。 |
%(输出文件名)s |
缩略图应复制的临时文件的路径 |
%(临时目录)s |
包含%(outfile) 的临时目录,并且在创建缩略图期间可能需要的其他临时文件也可以使用 |
如果创建的图像(在%(outfile)
处)的大小大于%(size)
,AllMyToes将相应地缩小图像。AllMyToes还会执行其他必要的转换,例如将图像转换为每通道8位的RGBA PNG图像并添加所有必要的元数据块。因此,命令可以提供任何支持的图像格式的缩略图。AllMyToes还会确保将图像转换为符合freedesktop.org规范的缩略图。
键 meta
freedesktop.org缩略图具有“元数据块”,以键值对形式的元数据属性。(参见元数据块的解释。)提供者也可以提供这样的元数据条目。其中一些甚至被标准推荐(Thumb::Document::Pages
用于面向纸张的文档,以及Thumb::Movie::Length
用于视频文件的总秒数)。
提供者规范中的meta
键包含一个字典,将元数据键映射到命令列表。对于每个键,执行命令列表,从上到下,直到其中一个命令成功退出并返回0
。必须通过stdout
返回元数据块的价值。
在当前实现中,如果元数据块的任何命令都不成功,则缩略图生成将失败。元数据块的命令可以使用与图像创建命令相同的变量。
元数据块的规范是可选的。
键 revision
修订键旨在作为提供者的“版本”。它是可选的,目前除了作为元数据块添加到缩略图之外,没有其他效果。
这个想法是将来可以使用这个修订号重新创建缩略图,如果有一个提供者具有更高的修订号。
关于命令的注意事项
对于commands
键中的图像命令以及meta
键下的命令,都应该考虑一些事情。
首先,命令可以是多行shell脚本,只需在YAML文件中使用多行字符串即可。以下为SVG提供者的示例,说明了多行命令可能的样子
- mimes:
- image/svg+xml
commands:
- |
which inkscape || exit 1
w=$(inkscape -W "%(file)s" | sed 's/\..*//')
h=$(inkscape -H "%(file)s" | sed 's/\..*//')
test $w -gt $h && size_arg="-w %(size)s" || size_arg="-h %(size)s"
inkscape --export-area-page --export-type=png $size_arg -o "%(tmpdir)s/outfile.png" "%(file)s" && \
mv "%(tmpdir)s/outfile.png" "%(outfile)s"
- |
convert -background none -resize %(size)sx%(size)s "%(file)s" "%(tmpdir)s/outfile.png" && \
mv "%(tmpdir)s/outfile.png" "%(outfile)s"
其次,命令应该是POSIX shell兼容的,例如不要依赖于BASH。这保证了提供者命令将在大多数机器和账户上工作。
第三,如果某些环境先决条件没有满足,命令应该以返回码> 0
失败。请记住,无论早期命令是否失败,命令的管道将退出最后一个命令的返回码。
因此,使用 &&
将程序链起来或使用 || exit 1
来扩展程序调用,以便正确地使提供程序命令失败,这是一个好主意。例如,可以使用 which <program> || exit 1
来测试管道中使用的所需程序的可用性。
还要记住要 引用输入文件(例如 "%(file)s"
),因为路径可能包含空格。不应在 %(outfile)s
(以及 %(tmpdir)s
)中包含任何空格,但引用它们也无妨。
示例
让我们看一个示例,并指定一个为 PDF 和 postscript 文件提供缩略图的提供程序。两者都可以使用相同的命令转换为缩略图,这就是为什么可以将两者处理在一个提供程序中。
请注意,AllMyToes 的实际默认配置使用不同的提供程序定义来实现更具体的元块命令。这个定义仅作为示例。
PDF 文件的 MIME 类型为 application/pdf
,postscript 文件的 MIME 类型为 application/postscript
。
- mimes: [application/pdf, application/postscript]
commands:
- evince-thumbnailer -s %(size)s "%(file)s" %(outfile)s
- convert -thumbnail %(size)sx%(size)s -background white %(file)s[0] PNG:%(outfile)s
meta:
'Thumb::Document::Pages':
- |
which exiftool || exit 1
exiftool "%(file)s" | awk '/^Page Count/ {print $4}' | sed 's/[^0-9]*//g'
- |
which gs || exit 1
gs -o /dev/null -sDEVICE=bbox "%(file)s" 2>&1 | grep HiResBoundingBox | wc -l
revision: 1
首先,定义此提供程序将使用的 MIME 类型。
commands
部分首先尝试使用 evince-thumbnailer
在 %(outfile)s
中创建缩略图。如果 evince-thumbnailer
存在,则提供图像的任务已完成,不会执行第二个命令。
如果 evince-thumbnailer
不可用,第一个命令将失败,AllMyToes 将执行第二个命令,该命令使用 ImageMagick 的 convert
。如果 convert
也不可用,则缩略图创建失败,AllMyToes 将返回错误。
首先尝试 evince-thumbnailer
,因为它更快,我们更喜欢使用它。
如果两个命令中的任何一个成功,AllMyToes 将评估 meta
部分。在这个例子中,我们只有一个具有元键 Thumb::Document::Pages
的元块。此元块也有两个命令,同样,如果第一个命令失败,AllMyToes 将仅执行第二个命令。
第一个命令依赖于 exiftool
,第二个命令依赖于 Ghostscript(gs
)。因为它们都用于管道中,所以我们首先检查它们是否存在,如果不存在则退出并返回 1
。示例展示了如何将多行脚本用作命令。
两个元数据命令都返回值作为输出到 stdout
的 Thumb::Document::Pages
元数据块的值。
有关更多示例,请参阅 默认提供程序配置。
这有什么用?
我的个人动机是使用缩略图来预览终端文件管理器中的图像,如 joshuto 和 ranger 中的图像。但是,AllMyToes在任何需要以脚本环境显示尺寸受限图像的情况下都可能很有用,例如作为桌面通知中的图标,或在基于终端的应用程序中的其他图像叠加,或桌面小部件;在这些情况下,加载全尺寸图像会消耗不必要的的时间和CPU资源。
安装
Linux X86-64 二进制文件(实验性)
从发布页面下载最新版本的二进制文件。使下载的文件可执行(chmod +x allmytoes
)并将其放置在您的PATH
目录中(例如mv allmytoes ~/local/bin
)。
通过cargo
的最新发布版
cargo install allmytoes
通过cargo
获取最新版本
cargo install --git https://gitlab.com/allmytoes/allmytoes.git
从仓库克隆
git clone https://gitlab.com/allmytoes/allmytoes.git
cd allmytoes
cargo build --release
生成的二进制文件将在target/release/allmytoes
。
一些规格
- Freedesktop.org 缩略图规范:AllMyToes努力遵守freedesktop.org 缩略图规范。现在应该实现了标准的所有相关部分。
- AllMyToes不会创建缓存目录(
$XDG_CACHE_HOME
或~/.cache
)。如果缓存目录不存在,AllMyToes将以错误终止。(以后可能会改变。) - 如果不存在,AllMyToes将在缓存目录下创建缩略图目录和特定大小的子目录。
- AllMyToes只接受常规文件和常规文件的符号链接作为输入。将来可能会支持目录。没有计划支持其他文件类型。
缩略图元数据块
缩略图 - 所有都是PNG格式 - 具有一定的元数据条目,每个条目都是一个PNG“tEXt”块,具有键和值。freedesktop.org 缩略图标准描述了一些必需的和一些可选的键。(见标准中的“缩略图创建部分”)。AllMyToes实现了所有这些。以下表格列出了AllMyToes创建的所有元数据条目。
键 | XDG 标准 | 描述 |
---|---|---|
Thumb::URI |
必需 | 缩略图源文件的URI。 |
Thumb::MTime |
必需 | 缩略图源文件的mtime。(功能上必需。) |
Software |
可选 | 创建缩略图的软件的名称。也被PNG标准描述。 这始终设置为 allmytoes 。 |
Software::Version |
- | 创建缩略图的AllMyToes的版本。 |
AMT::ProviderRevision |
- | 对于来自提供者(非图像源)的缩略图,根据配置提供的提供者修订版。 |
Thumb::Size |
可选 | 缩略图源文件的大小,以字节为单位。 |
Thumb::Mimetype |
可选 | 缩略图源文件的mimetype。 |
Thumb::Image::Width |
可选 | 源图像的宽度,以像素为单位。† |
Thumb::Image::Height |
可选 | 源图像的高度,以像素为单位。† |
Thumb::Image::Dimensions |
- | 一个字符串 <宽度>x<高度> ,描述了缩略图源图像的尺寸。† |
Thumb::Image::重定向 |
- | 对创建缩略图时进行的旋转和翻转的文本描述,基于缩略图源图像的EXIF数据。 仅当缩略图的来源是包含 Orientation 标志的EXIF数据的图像格式时。 |
Thumb::文档::页数 |
可选 | 页数(仅适用于PDF和PostScript文件)。 |
Thumb::电影::长度 |
可选 | 视频长度(秒,仅适用于视频文件)。 |
† 仅适用于图像输入文件
路线图
计划的主要里程碑
- 遵守 freedesktop.org 规范的强制要求,并具有基本健壮性(见 %1)。然后 AllMyToes 将升级到 0.1.0 版本。
- 通过配置提供预览的其他程序支持非图像文件格式(视频、字体、文档等)。(#13)
- 支持 共享仓库。
- 根据配置的路径模式支持其他缩略图仓库位置。(不属于 freedesktop.org 标准。)
另请参阅 我的开发板。
测试
一些东西通过标准 Rust 单元测试进行测试。可以使用 cargo test
运行这些测试。
大多数 AllMyToes 功能通过 BDD 测试框架进行端到端测试,该框架是 Python Behave。这些测试使用文件系统上的真实图像和一个 allmytoes
调试构建,作为子进程启动。
BDD 测试位于 test
子目录中。测试定义作为 feature
-文件位于 test/features
中。
运行 BDD 测试
拥有 Python >= 3.10 环境和所需的依赖项。例如,使用 virtualenv,然后运行 pip install -r test/requirements.txt
。
拥有 AllMyToes 的 调试 构建。 target/debug/allmytoes
将是受测试的二进制文件。
然后,要运行测试,请使用 cd
进入 test
目录并运行 behave
。
关于缺少的测试/未测试事物的说明
XDG_CACHE_HOME
的评估- 对错误和缺失的文件扩展名进行 MIME 类型探测(如果 CI 失败,请检查是否在使用的 docker img 上安装了 MIME-db)
--force-creation
- 当输入文件不可读时返回错误,无论是否存在有效的缩略图。
- 更新现有但过时的缩略图
- 在不存在、不可读、无法解码的输入文件上出错
- 拒绝处理既不是常规文件也不是常规文件符号链接的文件
- 所有 tEXt 元数据(mtime 和 URI 是隐式测试的,当然)
- #61
您可能更喜欢使用此替代方案
-
Tumbler 是一个功能更丰富且更为成熟的用于同一目的的工具,但需要作为服务运行,并使用 DBUS 进行通信。
我没有使用 Tumbler,因为我想要为我的脚本拥有更简单的东西。
AllMyToes 作为 Rust 库
AllMyToes 可以作为一个 Rust 库来获取给定图片的缩略图。您可以在 crates.io 上找到这个软件包。
AllMyToes 具有非常简洁的接口。有一个用于配置的 struct(AMT
),它还提供了一个获取缩略图的功能(get
)。然后,有一个枚举类型用于指定缩略图大小(ThumbSize
),一个用于结果的 struct(Thumb
),以及一个用于可能的错误类型的枚举(ToeErrorType
)。
示例
use std::path::Path;
use allmytoes::{AMTConfiguration, AMT, ThumbSize};
fn main() {
// The configuration for allmytoes
// Usually, the defaults are fine.
let configuration = AMTConfiguration::default();
// An instance of allmytoes that can be used to provide thumbnails
let amt = AMT::new(&configuration);
// The file for which we want a thumbnail as a `std::path::Path`.
let input_file = Path::new("/tmp/image.jpg");
// The size of the thumbnail we want
let thumb_size = ThumbSize::Large;
// Get a thumbnail
match amt.get(
input_file,
thumb_size,
) {
Ok(thumb) => {
println!("The thumb is here: {}", thumb.path)
}
Err(error) => println!(
"Error '{:?}' occurred when trying to provide the thumb. ({})",
error,
error.msg(),
),
}
}
许可协议:GPL 3
AllMyToes 是免费软件:您可以在自由软件基金会发布的 GNU 通用公共许可证的条款下重新分发和/或修改它,许可证版本为 3,或者(根据您的选择)许可证的任何后续版本。
AllMyToes 的分发旨在使其有用,但没有任何保证;甚至没有关于其商售性或适用于特定目的的隐含保证。有关详细信息,请参阅 GNU 通用公共许可证。
您应已收到 GNU 通用公共许可证的副本。如果没有,请参阅 https://gnu.ac.cn/licenses/。
依赖关系
~12–19MB
~272K SLoC