CLI-Anything GIMP:基于 Pillow 的无 GUI 有状态图像编辑命令行工具实战指南
【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything
导读
本文围绕 skills/cli-anything-gimp/SKILL.md 展开,深入讲解cli-anything-gimp——一个专为 AI Agent 与命令行重度用户设计的有状态图像编辑 CLI。它以 Pillow 为默认渲染引擎,支持项目化图层合成、滤镜链、渲染期绘制操作与 50 层撤销历史,并可在安装 GIMP 后自动切换到原生 Script-Fu 批处理后端。读完本文,你将掌握从项目创建、图层与滤镜操作、导出渲染到 Agent 化 JSON 输出的完整实战方法,并理解双渲染后端的底层实现原理。
安装与前置条件
cli-anything-gimp以 Python 包形式分发,安装命令如下:
pip install cli-anything-gimp根据 gimp/agent-harness/cli_anything/gimp/README.md 与 SKILL 文档,运行依赖为:
- Python 3.10+(硬性要求);
- Pillow:图像处理核心引擎,也是默认渲染路径的依赖;
- click:CLI 框架,负责命令分组与参数解析;
- numpy:混合模式(blend modes)的像素级计算与直方图分析;
- prompt_toolkit(可选):交互式 REPL 模式下提供补全与历史记录。
手动安装依赖可使用:
pip install Pillow click numpy prompt_toolkit关于 GIMP 本身的定位需要特别说明:GIMP 是可选的推荐项,而非必须项。SKILL 文档明确指出:GIMP 用于原生批处理渲染,但当 GIMP 不可用或项目中存在延迟draw操作时,分层合成会走内置的 Pillow 渲染路径。从源码看,export.py 中的渲染函数会先探测 GIMP 后端,失败后自动降级到 Pillow,整个过程对使用者透明。
快速上手:基本命令与 REPL 模式
一次性命令(One-shot)
# 查看帮助 cli-anything-gimp --help # 创建新项目 cli-anything-gimp project new -o project.json # 以 JSON 输出运行(供 Agent 消费) cli-anything-gimp --json project info -p project.json交互式 REPL
不带子命令直接启动即可进入 REPL 会话:
cli-anything-gimp # 交互式输入命令,支持 tab 补全与历史记录 # 输入 'help' 查看可用命令,'quit' 退出REPL 的核心实现在 gimp_cli.py 中:当 click 主组检测到未调用子命令时,会自动ctx.invoke(repl, ...)。REPL 使用shlex.split解析输入行(因此带空格的文本参数可安全使用引号),每条命令通过cli.main(args, standalone_mode=False)复用于命令管线,且help、quit为 REPL 层内建命令。
全局选项
| 选项 | 说明 |
|---|---|
--json | 输出结构化 JSON,供机器/Agent 解析 |
--project PATH | 指定.gimp-cli.json项目文件,命令执行前自动加载 |
--dry-run | 执行命令但不将状态变更写入磁盘 |
值得注意的实现细节:CLI 注册了result_callback,在一次一次性命令结束后,若会话状态被修改且未处于--dry-run或 REPL 模式,会自动调用sess.save_session()落盘,实现"命令即保存"的体验(见 gimp_cli.py 中的auto_save_on_exit)。
命令组全景解析
SKILL 文档将全部命令划分为八个组。以下结合源码逐一展开参数与行为细节。
Project(项目管理)
| 命令 | 描述 |
|---|---|
new | 创建新项目 |
open | 打开已有项目 |
save | 保存当前项目 |
info | 显示项目信息 |
profiles | 列出可用画布模板 |
json | 打印原始项目 JSON |
project new支持--width、--height、--mode(RGB/RGBA/L/LA)、--background(默认#ffffff)、--dpi(默认 72)、--name(默认 untitled)以及--profile。当指定--profile时,会从 project.py 中的PROFILES字典直接覆盖宽高与 DPI:
| 模板名 | 尺寸 | DPI |
|---|---|---|
hd1080p | 1920×1080 | 72 |
hd720p | 1280×720 | 72 |
4k | 3840×2160 | 72 |
square1080 | 1080×1080 | 72 |
a4_300dpi | 2480×3508 | 300 |
a4_150dpi | 1240×1754 | 150 |
letter_300dpi | 2550×3300 | 300 |
web_banner | 1200×628 | 72 |
instagram_post | 1080×1080 | 72 |
instagram_story | 1080×1920 | 72 |
twitter_header | 1500×500 | 72 |
youtube_thumb | 1280×720 | 72 |
icon_256 | 256×256 | 72 |
icon_512 | 512×512 | 72 |
项目文件是带版本号的 JSON(version: "1.0"),包含canvas、layers、selection、guides与metadata字段;open会校验version与canvas字段是否存在,否则视为无效项目文件。
Layer(图层管理)
| 命令 | 描述 |
|---|---|
new | 新建空白图层 |
add-from-file | 从图片文件添加图层 |
list | 列出全部图层 |
remove | 按索引删除图层 |
duplicate | 复制图层 |
move | 移动图层到新位置 |
set | 设置图层属性(name、opacity、visible、mode、offset_x、offset_y;天然接受负偏移值) |
flatten | 展平所有可见图层 |
merge-down | 与下方图层合并 |
图层索引从 0 开始,0 代表堆栈顶层。layer new的--type可选image/text/solid,--fill支持transparent、white、black或十六进制颜色,--opacity取值 0.0–1.0,--mode为混合模式。
layer set的底层实现位于 layers.py 的set_layer_property,各属性的校验规则为:
opacity:浮点,必须落在 0.0–1.0;visible:true/1/yes视为可见,其余为不可见;mode(或blend_mode):必须是BLEND_MODES列表中的合法值;name:直接替换字符串;offset_x/offset_y:转为整数存储,支持负值(SKILL 文档特别强调命令模式与 REPL 模式均支持负偏移)。
flatten与merge-down采用延迟执行策略:命令只是打上_flatten_pending/_merge_down_pending标记,真正的像素合并发生在export render阶段。
add-from-file有一个实用细节:它会先通过纯 Python 的头解析读取图片尺寸(支持 PNG/JPEG/GIF/BMP/WEBP/TIFF),因此图层尺寸无需依赖 Pillow 即可准确记录。
Canvas(画布操作)
| 命令 | 描述 |
|---|---|
info | 显示画布信息 |
resize | 调整画布尺寸(不缩放内容) |
scale | 等比缩放画布与全部内容 |
crop | 裁剪画布到指定矩形 |
mode | 设置画布色彩模式 |
dpi | 设置画布 DPI |
canvas resize --width W --height H [--anchor ...]:仅增删画布空间而不缩放内容。--anchor决定原内容在新画布中的锚定方位,支持center、top-left、top-right、bottom-left、bottom-right、top、bottom、left、right。源码会计算(dx, dy)偏移量并累加到每个图层的offset_x/offset_y上(见 canvas.py)。canvas scale --width W --height H [--resample lanczos|bicubic|bilinear|nearest]:等比缩放画布与内容。与 resize 不同,它记录每层的_scale_x/_scale_y缩放因子并在渲染期执行重采样,同时按比例更新图层宽高与偏移。canvas crop --left L --top T --right R --bottom B:裁剪后自动为各图层偏移减去(left, top),保持内容的相对位置正确。canvas mode:可在RGB、RGBA、L、LA、CMYK、P之间切换。canvas dpi:设置打印分辨率,canvas info会据此计算物理尺寸(英寸)与百万像素数。
Filter(滤镜管理)
| 命令 | 描述 |
|---|---|
list-available | 列出全部可用滤镜(可按类别过滤) |
info | 查看滤镜详情 |
add | 为图层添加滤镜 |
remove | 按索引移除滤镜 |
set | 设置滤镜参数 |
list | 列出图层上的滤镜 |
滤镜注册表定义在 filters.py 的FILTER_REGISTRY中,按四类组织:
- Adjustment(调整):
brightness、contrast、saturation、sharpness、autocontrast、equalize、invert、posterize、solarize、grayscale、sepia - Blur(模糊/锐化):
gaussian_blur、box_blur、unsharp_mask、smooth - Stylize(风格化):
find_edges、emboss、contour、detail - Transform(变换,渲染期应用):
rotate、flip_h、flip_v、resize、crop
每个滤镜都声明了参数的类型、默认值与取值范围。例如:
brightness/contrast/saturation/sharpness:factor(float,默认 1.0,范围 0.0–10.0;1.0 为中性,大于 1 增强,小于 1 减弱);gaussian_blur/box_blur:radius(默认 2.0,范围 0.1–100.0);unsharp_mask:radius(默认 2.0)、percent(默认 150)、threshold(默认 3);posterize:bits(默认 4,1–8);solarize:threshold(默认 128,0–255);sepia:strength(默认 0.8,0.0–1.0);rotate:angle(-360 到 360)、expand(bool,默认 True)。
filter add --param key=value支持重复传参,参数会先被尝试解析为数字(含小数点转为 float,否则转 int),随后经validate_params做类型转换、范围校验与默认值填充;未知参数会直接报错。filter set同样走校验逻辑,确保滤镜链在任何时候都处于合法状态。
Media(媒体文件操作)
| 命令 | 描述 |
|---|---|
probe | 分析图片文件 |
list | 列出项目引用的媒体文件 |
check | 检查所有引用的媒体文件是否存在 |
histogram | 显示图片直方图分析 |
media probe优先使用 Pillow 提取丰富元数据(尺寸、模式、格式、DPI、EXIF 的 Make/Model/ISO/快门等信息、动图帧数、调色板数量、位深),当 Pillow 不可用时降级为纯 Python 头部解析。media histogram返回 RGB 或亮度通道的最小/最大/均值统计(见 media.py)。media check对 Agent 尤其重要——它能在渲染前发现丢失的源图片,避免导出时出现空白层。
Export(导出/渲染)
| 命令 | 描述 |
|---|---|
presets | 列出导出预设 |
preset-info | 查看预设详情 |
render | 渲染项目为图片文件;延迟 draw 操作在渲染期应用 |
export render的签名:export render <output> [--preset name] [--overwrite] [--quality Q] [--format F]。可用预设定义于 export.py 的EXPORT_PRESETS:
| 预设 | 格式 | 参数 |
|---|---|---|
png | PNG | compress_level=6 |
png-max | PNG | compress_level=9 |
jpeg-high | JPEG | quality=95, subsampling=0 |
jpeg-medium | JPEG | quality=80 |
jpeg-low | JPEG | quality=60 |
webp | WEBP | quality=85 |
webp-lossless | WEBP | lossless=True |
tiff | TIFF | compression=lzw |
tiff-none | TIFF | 无 |
bmp | BMP | 无 |
gif | GIF | 无 |
pdf | 无 | |
ico | ICO | 无 |
--overwrite用于覆盖已存在文件(否则报FileExistsError);--quality与--format可覆盖预设参数。渲染结果会返回输出路径、格式、尺寸、文件大小(含人类可读形式)、使用的预设、渲染方法与实际渲染的图层数。
Session(会话管理)
| 命令 | 描述 |
|---|---|
status | 显示会话状态 |
undo | 撤销上一个操作 |
redo | 重做已撤销的操作 |
history | 显示撤销历史 |
Draw(绘制,渲染期应用)
| 命令 | 描述 |
|---|---|
text | 在图层上绘制文本(转为文本图层操作) |
rect | 绘制矩形(存储为绘制操作) |
draw text的参数:--layer L --text "..." [--x X] [--y Y] [--font F] [--size S] [--color C];draw rect的参数:--layer L --x1 --y1 --x2 --y2 [--fill C] [--outline C] [--width N]。两者均写入图层的draw_ops列表,在渲染时由渲染管线统一应用。
实战示例:分层合成工作流
创建新项目
cli-anything-gimp project new -o myproject.json # 或指定尺寸/模板 cli-anything-gimp project new --width 1920 --height 1080 --profile hd1080p -o myproject.json # 程序化使用 JSON 输出 cli-anything-gimp --json project new -o myproject.json交互式 REPL 会话
cli-anything-gimp # 交互式输入命令 # 输入 'help' 查看可用命令 # 使用 'undo' 和 'redo' 进行历史导航导出项目
cli-anything-gimp --project myproject.json export render output.png --overwrite叠加型合成工作流(SKILL 文档核心示例)
cli-anything-gimp --project poster.gimp-cli.json layer set 0 offset_x -48 cli-anything-gimp --project poster.gimp-cli.json layer set 0 offset_y 24 cli-anything-gimp --project poster.gimp-cli.json draw text --layer 0 --text "Launch Night" --x 96 --y 120 --size 72 --color "#f6f1e8" cli-anything-gimp --project poster.gimp-cli.json export render output.png --overwrite使用要点(SKILL 文档原注):
layer set在命令模式与 REPL 模式下均接受负的offset_x/offset_y值;draw text与draw rect是渲染期操作——应以导出的图片而非项目 JSON 作为审查对象;- 存在延迟 draw 操作的项目,即使安装了 GIMP,也默认走 Pillow 渲染路径(更稳定)。
完整照片处理流程(摘自包内 README)
# 创建项目 cli-anything-gimp project new --width 1920 --height 1080 --profile hd1080p -o edit.json # 添加图片图层 cli-anything-gimp --project edit.json layer add-from-file photo.jpg --name "Background" # 应用滤镜链 cli-anything-gimp --project edit.json filter add brightness --layer 0 --param factor=1.2 cli-anything-gimp --project edit.json filter add contrast --layer 0 --param factor=1.1 cli-anything-gimp --project edit.json filter add saturation --layer 0 --param factor=1.3 # 添加文本叠加 cli-anything-gimp --project edit.json layer new --type text --name "Title" cli-anything-gimp --project edit.json draw text --layer 0 --text "My Photo" --size 48 --color "#ffffff" # 查看图层堆栈 cli-anything-gimp --project edit.json layer list # 保存并渲染 cli-anything-gimp --project edit.json project save cli-anything-gimp --project edit.json export render output.jpg --preset jpeg-high --overwrite混合模式
图层合成支持的混合模式共 15 种:normal、multiply、screen、overlay、soft_light、hard_light、difference、darken、lighten、color_dodge、color_burn、addition、subtract、grain_merge、grain_extract。Pillow 路径下由 export.py 中的_blend_with_mode使用 numpy 逐通道实现;GIMP 路径则映射到等价的 Script-Fu 图层模式常量。
状态管理:有状态的会话模型
CLI 的"有状态"特性由 session.py 的Session类实现:
- Undo/Redo:最多保留 50 层历史。每次变更前调用
snapshot()深拷贝当前项目快照(含描述与时间戳)压入撤销栈,并清空重做栈;undo()将当前状态存入重做栈后回滚,redo()反向操作; - Project persistence:项目状态以 JSON 持久化,保存时使用
fcntl文件锁进行原子写入(_locked_save_json),避免并发写坏文件; - Session tracking:
status命令返回是否有项目、项目路径、是否修改、撤销/重做栈深度与项目名; - 自动保存:一次性命令结束后若会话被修改,会自动将项目写回磁盘(见前文
auto_save_on_exit)。
输出格式:人类可读与机器可读双模式
所有命令都支持两种输出:
- 人类可读(默认):以缩进表格、键值对、颜色化的格式化文本输出(
_print_dict/_print_list实现); - 机器可读(
--json):输出缩进的结构化 JSON,供 Agent 直接解析。
# 人类输出 cli-anything-gimp project info -p project.json # Agent 用 JSON 输出 cli-anything-gimp --json project info -p project.json错误处理同样双轨:在--json模式下错误会被序列化为{"error": ..., "type": ...}结构,非 JSON 模式则输出到 stderr;一次性命令失败时进程以非零码退出,而 REPL 模式下仅打印错误并继续会话。
双渲染后端原理:GIMP Script-Fu 与 Pillow 回退
这是本工具最值得深入理解的部分。渲染管线的调度逻辑位于 export.py 的render():
- 先探测 GIMP 后端:
is_available()检查gimp、gimp-2.10、gimp-2.99是否在 PATH 中(见 gimp_backend.py); - 若 GIMP 可用且项目不含
draw_ops,则生成一段完整的 Script-Fu 表达式,通过gimp -i -b批处理模式完成:创建画布 → 自底向上插入可见图层(含混合模式、透明度、偏移、滤镜链)→ 展平 → 按预设导出; - 其余情况(无 GIMP、或项目含延迟 draw 操作)一律回退到 Pillow 路径。
Pillow 路径的关键步骤(见_render_via_pillow):
- 按画布背景色与色彩模式创建基底图像(RGBA/LA 支持透明背景合成);
- 自底向上(
reversed(layers))遍历可见图层,跳过隐藏层; - 每层经过
_load_layer(image 层读源文件或填充色、solid 层生成纯色块、text 层渲染文本)、_apply_filters(按滤镜注册表引擎逐个应用:pillow_enhance对应ImageEnhance系列、pillow_ops对应ImageOps系列、pillow_filter对应ImageFilter系列、pillow_transform对应旋转/翻转/缩放/裁剪、custom实现 sepia)、_apply_draw_ops(应用延迟的 rect/text 绘制操作); - 应用
_scale_x/_scale_y缩放与偏移,再以对应混合模式合成到画布; - JPEG 输出前将 RGBA 合到白底,GIF 输出前量化到 256 色调色板,DPI 信息写入导出参数。
从源码结构可以推断:这种"GIMP 原生优先、Pillow 兜底"的设计,既能在 GIMP 环境中获得原生的图像处理质量,又能保证在任何仅有 Python 依赖的环境中稳定渲染出图。
For AI Agents:程序化调用规范
SKILL 文档为 Agent 集成给出六条明确规范:
- 始终使用
--json标志,获取可解析的结构化输出; - 检查返回码——0 为成功,非零为失败;
- 解析 stderr——失败时的错误信息位于 stderr;
- 所有文件操作使用绝对路径;
- 导出操作后验证输出文件存在;
- 在偏移、绘制、混合模式或滤镜变更后,审查渲染输出而不是只信任保存的项目状态(因为 flatten/merge-down/draw 均为渲染期生效,项目 JSON 只记录意图,不反映最终像素)。
这套规范与项目内的端到端测试相互印证:例如 tests/test_full_e2e.py 会创建真实测试图片,逐像素验证亮度滤镜确实提升了像素值、验证图层堆叠顺序(新图层默认在顶层)等行为,保证了命令语义的可信度。
运行测试
在仓库内可运行包自带的测试套件验证行为:
cd gimp/agent-harness python3 -m pytest cli/tests/test_core.py -v # 单元测试(无需图片) python3 -m pytest cli/tests/test_full_e2e.py -v # 端到端测试(会生成测试图片) python3 -m pytest cli/tests/ -v # 全部测试测试覆盖项目生命周期往返(create→save→open)、图层操作、滤镜渲染的像素级结果、画布缩放/裁剪、媒体探测与会话撤销栈等核心能力,可作为理解命令语义与验证环境可用性的直接参考。
更多信息
- 完整命令参考与开发指南:gimp/agent-harness/cli_anything/gimp/README.md
- 测试说明:gimp/agent-harness/cli_anything/gimp/tests/TEST.md
- 方法论:
cli-anything-plugin的 HARNESS.md(见 cli-anything-plugin/HARNESS.md) - 当前版本:1.0.0
结语
cli-anything-gimp用一个 JSON 项目文件承载图层的"编辑意图"(图层栈、滤镜链、偏移、绘制操作),把像素级的重计算推迟到渲染阶段,并通过 GIMP/Pillow 双后端保证了环境适应性。对于 AI Agent 而言,配合--json、返回码与渲染期审查规范,它可以被可靠地编排进自动化图像生产流水线;对于命令行用户而言,它也提供了脚本化、可复现的图像编辑能力,是"让软件 Agent 原生可用"理念在图像编辑领域的落地实践。
【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考