参数顺序会影响结果,但不知道为什么
ImageMagick 的参数分成两类:配置后续行为的设置类,和立即生效的操作类。理解这个区别能解释掉大部分令人困惑的结果。
你挪了一个参数的位置,结果完全变了;或者某个参数看起来根本没起作用。这是能解释大部分 ImageMagick 怪异行为的概念,而官方文档的入门部分几乎没提。
两类参数
设置类 —— 配置写在它后面的东西
-density、-size、-background、-gravity、-fill、-font、-pointsize、-delay、-loop、-quality、-channel、-compose、-bordercolor、-filter。
它们改变的是状态,作用于写在它们后面被读入或绘制的图像。放得太靠后就完全不起作用。
操作类 —— 立即执行
-resize、-crop、-rotate、-flip、-composite、-annotate、-border、-extent、-trim、-blur、-negate。
它们对已经载入的图像立即生效,按书写顺序从左到右依次执行。
典型踩坑
-density 要写在 PDF 前面
magick -density 300 in.pdf out.png # 正确 —— 按 300 DPI 渲染
magick in.pdf -density 300 out.png # 错误 —— 按 72 渲染完了才标成 300
第二条会得到一张糊图,元数据还写着 300。这是最常见的顺序错误。
-size 要写在生成型图源前面
magick -size 800x600 xc:white out.png # 正确 —— 800x600
magick xc:white -size 800x600 out.png # 错误 —— 1x1 像素
-background 要写在 -extent 前面
magick in.jpg -background white -gravity center -extent 1200x1200 out.jpg # 正确
magick in.jpg -gravity center -extent 1200x1200 -background white out.jpg # 补边不是白色
-delay 要写在帧前面
magick -delay 8 -loop 0 frame_*.png out.gif # 正确
magick frame_*.png -delay 8 -loop 0 out.gif # 时间设置被忽略
操作类按顺序执行
magick in.jpg -resize 400x400 -crop 200x200+0+0 +repage out.jpg
magick in.jpg -crop 200x200+0+0 +repage -resize 400x400 out.jpg
第一条先缩到 400×400,再取一块 200×200 的角。第二条从原图取一块 200×200,再放大到 400×400。两条都合法,出来的是完全不同的图。
设置会一直保持,直到被改变
magick in.jpg -gravity south -annotate +0+20 'Bottom' \
-gravity north -annotate +0+20 'Top' out.jpg
第一个 -gravity 一直有效,直到第二个把它换掉。忘记重设某个设置,是「为什么我第二段文字位置不对」的常见原因。
有些设置用加号形式取消:-channel A 对应 +channel,-repage 对应 +repage。一般来说减号设置、加号取消。
括号限定作用范围
magick in.jpg '(' logo.png -resize 20% ')' -gravity southeast -composite out.jpg
括号里的 -resize 20% 只作用于 logo.png。不加括号的话,它会作用于当前载入的所有图像 —— 这里就是两张都缩。
一个判断方法
把整条命令当成一串发给机器的指令,从左往右读,这台机器手里握着一叠图像。每看到一个参数就问自己:它是在描述「接下来那件事该怎么做」,还是它本身就在做一件事? 设置类要写在它所描述的东西前面,操作类写在你希望它发生的位置。