ImageMagick的基本使用

ImageMagick的基本使用

选项查询手册

简介与安装

ImageMagick简介

ImageMagick是一个开源的强大的图片处理库,可用来创建、编辑、合成或转换位图图像,比如:调整大小,翻转,镜像,旋转,扭曲,剪切和变换图像,调整图像颜色,应用各种特殊效果,或绘制文本,线,多边形,椭圆和贝塞尔曲线等等。

本文只列出我使用过的命令,并不是完整的教程,随着我平时使用的增加,文章会不断更新,命令会不断增加,当然如果我平时用的少,那可能就只会有这些了。

安装ImageMagick

由于我是macOS,所以使用macOS最常用的包管理器brew来安装

brew install imagemagick

命令使用格式

安装后,它主程序就一个magick,但它会有很多符号链接链接到magick,如下图所示
-w499

既然都是符号链接,从理论上来说,我用identify和用magick应该是一模一样的才对,但实际上却是这样的(如图所示)
image.jpg

我猜是因为它把命令本身也当成一个参数,当它识别到是identify时,它就会做输出图片简略信息的操作。事实上,identify是magick的子命令,所以我们还可以这样写
image.jpg

所以,所有的符号链接其实都是magick的子命令,通用的使用方法是

magick 子命令 参数

但magick却巧妙的给magick创建多个符号链接,并把符号链接名称命名为它的子命令名,这样在使用上就好像是多了一个可执行文件,其实内部还是通过识别符号链接的名称来自动识别到它是子命令,以达到简化命令的目的,让我们可以直接以下边这种方式调用

子命令 参数

常用命令

获取图片信息

#显示简略图片信息
identify /path/to/image.png

#显示详细图片信息
identify -verbose /path/to/image.png

缩放图片

使用resize缩放

#缩放到指定大小
convert /path/to/source.png -resize 200x200 /path/to/target.png

#按百分比缩放
convert /path/to/source.png -resize 50% /path/to/target.png

#多次缩放(本例是缩小再放大,效果就是变模糊了,可用于做马赛克)
convert /path/to/source.png -resize 50% -resize 200% /path/to/target.png

#只缩放宽,高按比例(省略高不写即可,但“x”号还是要写的)
convert /path/to/source.png -resize 200x /path/to/target.png

#只缩放高,宽按比例(省略宽不写即可,但“x”号还是要写的)
convert /path/to/source.png -resize x200 /path/to/target.png

#批量把iPhone拍的照片缩小成指定尺寸
declare -i j=0;for i in *.JPG; do convert $i -resize 1008x ${i:0:$[${#i}-4]}_resized.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

使用sample采样缩放(只采样不插值,一般用于做缩略图)

#原图的50%
convert image.png -sample 50% sample.png

#先缩小再放大,就是马赛克效果
convert image.png -sample 10% -sample 1000% sample.png

设置jpg图片质量

90表示转换为原质量的90%

convert input.jpg -quality 90 output.jpg

旋转图片

旋转90度(顺时针)

convert input.jpg -rotate 90 output.jpg

镜像图片

镜像图片其实就是水平翻转,使用-flop选项即可(-flip是垂直翻转)

# 水平翻转,就是我们平时说的镜像
convert input.jpg -flop output.jpg

# 垂直翻转,这个一般比较少用
convert input.jpg -flip output.jpg

裁剪图片

#从(50,50)坐标开始,裁剪一个100⨉100大小的图片(乘号用小写英文字母xyz的x就可以)
convert image.png -crop 100x100+50+50 crop.png

#不指定位置,则会把大图片分割成100⨉100的小图片,生成crop-0.png, crop-1.png, ……
convert image.png -crop 100x100 crop.png

把当前文件夹下的所有.jpg格式的图片都从(597,4)坐标开始(矩形左上角顶点),截取大小为1400×1076的图片,并且把图片名称的后27个字符(包括.jpg4个字符)去掉(后面再自己拼上)

declare -i j=0;for i in *.jpg; do convert $i -crop 1400x1076+597+4 ${i:0:$[${#i}-27]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

${i:m:n}表示从字符串i的第m位截取到第n位,在我这里i就是图片文件名(包括.jpg后缀),m是0,n是$[${#i}-27]${#i}是文件名i的总长度。

declare -i j=0;for i in *.jpg; do convert $i -crop 1080x2160+0+240 ${i:0:$[${#i}-29]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done
 
declare -i j=0;for i in *.jpg; do convert $i -crop 2002x1485+544+224 ${i:0:$[${#i}-4]}_crop.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

把当前文件夹下的所有.jpg格式的图片都从(0,453)坐标开始(矩形左上角顶点),截取大小为540×744的图片

declare -i j=0;for i in *.jpg; do convert $i -crop 540x744+0+453 ${i:0:$[${#i}-27]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

把当前文件夹下的所有.PNG格式的图片都从(414,4)坐标开始(矩形左上角顶点),截取大小为1530×1242的图片,同时把格式格式转为jpg

declare -i j=0;for i in *.PNG; do convert $i -crop 1530x1242+414+4 ${i:0:$[${#i}-4]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

$[${#i}-4]表示文件名总长度减4(其实就是去掉.PNG这个后缀,然后再自己拼上.jpg)。

declare -i j=0;for i in *.PNG; do convert $i -crop 1242x2000+0+208 ${i:0:$[${#i}-4]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

裁剪到图像边缘

这个功能也可以叫去除图片的空白,就好像对文本去除空格一样,图片也可以去除空白的像素,以得到能容纳图像的最小图片。

比如这是原始图片

我想裁剪成这样,就是除有效图片外的所有空白都裁掉

很简单,使用-trim选项即可

convert /path/to/input.jpg -trim /path/to/output.jpg

除了图片,也可以处理pdf格式(图片也可以使用这些参数)

convert -density 300 -trim -fuzz 1% +repage input.pdf output.pdf

-fuzz 1%主要是设置羽化,1%这个值可以自己看着来修改,-density 300表示设置图片dpi(分辨率)为300,300这个数字可以适当降低(数值越大文件越大),或者如果不用这个选项觉得图片质量可以,那也可以不用。

根据实验,-trim需要和-fuzz 1%+repage一起使用才可以达到截取到图片比较边缘的地方(即几乎不留空白)

convert -trim -fuzz 1% +repage /path/to/input.jpg /path/to/output.jpg

把当前目录下的所有.jpg(可自己修改)格式图片去除空白(即裁剪到图像的边缘)

declare -i j=0;for i in *.jpg; do convert -trim -fuzz 1% +repage $i ${i:0:$[${#i}-4]}_trimmed.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

抠图

"#FFFDF1"为要抠掉的背景色(也可写成rgb(255,253,241)这种格式),-fuzz 90%为允许误差(因为背景可能不是纯色),90%可以换成其它数字,反正我测试数字越大抠的越干净,而且只能用百分数,90%虽然是0.9,但不能写成0.9

convert /path/to/input.jpg -fuzz 90% -transparent "#FFFDF1" /path/to/output.png

批量抠图:把当前文件夹下的所有.jpg图片全部抠图

declare -i j=0;for i in *.jpg; do convert $i -fuzz 90% -transparent "#FFFDF1" ${i:0:$[${#i}-4]}.png;j=j+2;echo $j"."$i" convert succeed"!; done

修改背景颜色

-fill是填充的意思,-opaque是不透明的意思,意思是用-fill指定的颜色去填充(即替换)-opaque指定的颜色(原背景色)

convert /path/to/input.jpg -fuzz 25% -fill "#2DC844" -opaque "#FFFDF1" -flatten /path/to/output.jpg

-fuzz 25%是允许色差(因为你的背景色可能不是完全的纯色),这个数值自己按实际效果慢慢修改,反正25%我觉得不错,但我测试的是纯色背景,如果你的背景色不是纯色,那问题就比较多了。
-flatten意思是使用指定的背景色(有可能用-fill-background指定)创建一个虚拟画布,然后将原图合成到这个画面上。


无背景色png图片添加背景色,-background "#2DC844"用于指定背景色

convert /path/to/input.png -background "#2DC844" -flatten /path/to/output.jpg

批量操作:把当前目录下的所有.png格式的图片全部添加#FFFDF0背景色并裁剪掉一个像素(因为那是边)

# 裁剪出1620x3600的图片
declare -i j=0;for i in *.png; do convert $i -background "#FFFDF0" -flatten -crop 1620x3600+1+1 -quality 80 ~/Downloads/生成文件夹/${i:0:$[${#i}-4]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

# 裁剪出3456x2234的图片
declare -i j=0;for i in *.png; do convert $i -background "#FFFDF0" -flatten -crop 3456x2234+1+1 -quality 80 ~/Downloads/生成文件夹2/${i:0:$[${#i}-4]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

处理后的图片会被放到~/Downloads/生成文件夹/文件夹中,如果想放在当前文件夹中,可以把~/Downloads/生成文件夹/删除。

增加亮度

增加亮度(或降低亮度)有两个值,一个是亮度,一个是对比度,这个用过PS的应该都知道。

有两个参数可以使用,一个是-brightness-contrast,一个是-sigmoidal-contrast(-可变成+),参数格式如下

-brightness-contrast brightness{xcontrast}{%} 

-sigmoidal-contrast contrastxmid-point%
-sigmoidal-contrast brightnessx0% 增加亮度
+sigmoidal-contrast brightnessx0% 降低亮度
  • 花括号部分表示可以不写;
  • 对于-brightness-contrast,brightness和contrast的值都是-100到100之间,%可写可不写,但我习惯写,因为写了才知道是增加百分之几;
  • -sigmoidal-contrast contrastxmid-point%,一般把mid-point写成0,只调节contrast就相当于调节亮度(此时contrast就相当于是brightness);
  • mid-point表示曲线的中点,一般用0,也可以用其它数字,这个得看具体情况;
  • -sigmoidal-contrast前面的-变成+表示降低亮度(刚好与符号相反);
  • 但这两个参数具体有什么区别我还不知道;

实例:

convert input.jpg -brightness-contrast 5% output.jpg
convert input.jpg -sigmoidal-contrast 5x0% output.jpg

修改位深

convert source.jpg -depth 8 target.png

同时缩放和修改位深(用于压缩png图片)

convert /path/to/source.png -resize 1080x1920 -depth 8 /path/to/target.png

格式转换

直接在输出文件中用不同的后缀就行,它会自动识别后缀来转换

convert /path/to/source.png /path/to/target.jpg
convert /path/to/source.png /path/to/target.webp

把当前文件夹下的所有PNG图片转成JPG

#只转成jpg
declare -i j=0;for i in *.PNG; do convert $i ${i:0:$[${#i}-4]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

#转成jpg同时宽高压缩成原来的一半
declare -i j=0;for i in *.PNG; do convert $i -resize 50% ${i:0:$[${#i}-4]}.jpg;j=j+1;echo $j"."$i" convert succeed"!; done

注:${#i}表示获取i的长度,${i:m:n}表示从字符串i的第m个字符开始截取,共截取n个字符,感叹号不能放在双引号里面。

使用效果如下:
image.jpg

事实上它是可以直接处理多张图片的,不需要for循环,但仅限简单命令,如果是复杂命令,我试过不生效

convert *.png /path/to/target_%03d.jpg

%03d:与%d类似,都表示格式化为整数,只不过3表示至少显示3位,0表示如果不够3位,那就用0填充,整数上0可以换成其它符号,毕竟只是填充符号,但实际上在ImageMagick中只能用%03d%04d这样的格式,不能用%-3d%-4d等格式(否则它会把%当成普通字符打印出来)。

图片方向

下表从上到下,分别是从一个矩形的左上角开始顺时针旋转一圈,最终转到左下角,注意,英文说方向一般都是先说上下,再说左右,但是从5开始,它是先说左右,再说上下,因为它已经转了一圈回来了

imagemagick Orientation exif:Orientation
TopLeft 1
TopRight 2
BottomRight 3
BottomLeft 4
LeftTop 5
RightTop 6
RightBottom 7
LeftBottom 8

关于图片方向的知识,可以看:这个回答
关于iPhone拍照的方向,可以查看这里,请的非常详细。

imagemagick查看图片方向

# 方式一:格式化
identify -format '%[EXIF:Orientation]' /path/to/image.jpg

# 方式二:从所有图片信息里查找“Orientation”关键字
identify -verbose /path/to/image.jpg | grep Orientation

imagemagick设置图片方向,其中<方向>就是上表中的8个英文,注意设置方向是直接修改原图方向,不是生成新图片(当然还有一个特殊值,就是Undefined,也就是未定义,不带方向信息)

mogrify -orient <方向> IMG_4006.JPG

把当前文件夹下的所有图片方向都修改为TopLeft(即1)

declare -i j=0;for i in *.jpg; do mogrify -orient TopLeft $i;j=j+1;echo $j"."$i" convert succeed"!; done

多个操作一起使用

直接多个选项合并在一起就行了,比如我要裁剪一个透明png图片,又要给它填充一个背景色,那就是

convert /path/to/input.png -background "#FFFDF0" -flatten -crop 1620x3600+1+1 /path/to/output.jpg

其中-background "#FFFDF0" -flatten是填充背景色,-crop 1620x3600+1+1就是剪裁,但是要注意的是,如果你把裁剪放在填充背景色之前,它会无法裁剪(即生成的图片尺寸还是跟原图一样),我也不知道为什么,同理,可能还有其它的选项合在一起有顺序关系,这个自己试试就知道了。

添加文字水印

文字水印1:半透明、有旋转角度、有自定义字体、能指定位置、宽高为主图的百分比

magick nature.jpg -set option:watermarkWidth "%[fx:int(w*0.2)]" -alpha set -background none \( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 10 -undercolor "#00FF0070" -font 爱的目光无所不在.ttf -size "%[watermarkWidth]x" label:"这是水印" -gravity center -geometry +10+10  -rotate -25 \) -composite -quality 60 result.jpg
  • -set option:watermarkWidth "%[fx:int(w*0.2)]" -set option表示设置一个变量,watermarkWidth是变量名,"%[fx:int(w*0.2)]"是变量值;
  • "%[fx:int(w*0.2)]" fx表示函数,int(w*0.2)表示函数体,其中的w表示第一个输入图片的宽度(其实就是要添加水印的图片的宽度),整体意思是把主图宽度的0.2倍存到变量中,以后后面把水印宽度设置为这个宽度(高度按比较缩放,不用设置);
  • -alpha 开启alpha通道(透明通道);
  • set -background none 把背景设置为none,再加上又开始alpha通道,所以画布是透明的(这样就可以在上边画水印了);
  • -fill "#FFFFFF80" 填充颜色,前面6位是颜色,后面两位是透明度;
  • -stroke "#FF000080" 描边颜色,前面6位是颜色,后面两位是透明度;
  • -strokeWidth 10 指定描边宽度;
  • -undercolor "#00FF0070" 指定文字底色,前面6位是颜色,后面两位是透明度;
  • -font 爱的目光无所不在.ttf 指定字体路径,只支持ttf(如果不指定,中文会无法显示,英文一般都能显示,当然英文也可以指定字体);
  • -size "%[watermarkWidth]x" 设置水印的宽高,%[watermarkWidth]就是前面设置的变量,x是乘号(用英文字母xyz中的x即可),高没有写,表示自动按比例缩放;
  • label:"这是水印" 设置水印文字;
  • -gravity center -geometry +10+10 表示设置水印位置;
  • -gravity 指定9个位置中的一个,正好是在图片上画一个“米”字,“米”字的中心是一个位置,用英文center指定,另外8个位置分别为“东、南、西、北”以及它们斜角“东南、东北、西南、西北”,这些方向遵循地图上的位置定义(即:上北下南左西右东),当然是用英文的,全部小写,即:east, south, west, north, southeast, northeast, southwest, northwest;
  • -geometry +10+10 前面-gravity指定的位置都是刚好在边上的,用-geometry可以让跟边有一点距离,+10+10第一个+10表示横坐标距离,第二个+10表示纵坐标距离,注意这个距离是指距离它最靠近的那个边的距离,比如northeast的时候,就表示距离右边和上边的距离,而southwest的时候,就表示距离左边和下边的距离;
  • -rotate -25 旋转角度,可以是正也可以是负;
  • -composite 表示合成图片,其实前面是在把文字变成图片,最后用-composite表示两张图片叠在一起;
  • -quality 60 指定压缩等级,对于jpg,值为1-100质量逐渐升高,100的质量最好(但是也是会压缩的),因为jpeg格式本来就是有损压缩;而对于png格式,有0-9共10个等级,1-8,数字越大压缩越大,压缩越厉害(质量就越差),但具体解释非常复杂,总之从文件大小上看,1到8,文件是逐渐变小的,但9是例外,0和9质量都是最好,区别是压缩算法不同(0是zlib Z_RLE压缩,而9是Z_HUFFMAN_ONLY压缩),到底哪个更好,我也不知道,自己肉眼看吧。不过写0-9的时候,要写成10-90(为了跟jpeg保持一致),它会自动除以10,所以19表示级别1,21表示级别2;
  • 不想要设置的选项可以不指定,比如不想要底色,不想要描边,就不用写相对的选项;
  • 在Windows中括号不用转义,如果在行末用了\作为换行符,在Windows中要换成^

文字水印2:使用-pointsize设置字体大小

magick nature.jpg -alpha set -background none \( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 10 -font 爱的目光无所不在.ttf -pointsize 36 label:"这是水印" -gravity center -geometry +10+10  -rotate -25 \) -composite -quality 60 result.jpg
  • 使用了-pointsize可以设置字体大小,即字号,但一定要去掉-size,否则-pointsize会被-size覆盖,等于没设置。
  • 如果批量设置,我还是建议用-size而不是-pointsize,因为-size可以根据主图的比例来设置大小,当图片大小不一时,比例也能一致,但如果设置-pointsize那就没法按主图大小来设置了。

文字水印3:平铺水印

magick nature.jpg -set option:watermarkWidth "%[fx:int(w*0.2)]" -alpha set -background none -fill "#ffffff80" -font 爱的目光无所不在.ttf \( -size "%[watermarkWidth]x" label:"这是水印" -rotate 45 -write mpr:abc +delete \) \( +clone -tile mpr:abc -draw "color 0,0 reset" \) -composite result.jpg
  • 什么是mpr?,Memory Program Register,-write mpr:abc表示把它前面的配置写入到内存中,并命名为abc,后面使用的时候,就可以用mpr:abc来调用它。
  • +delete 删除序列中最后一个图片;
  • +clone 克隆序列中最后一个图片;
  • -draw "color 0,0 reset" 画图,(0,0)是坐标,表示从(0,0)开始画,reset是直接替换的颜色;

文字水印4:批量设置水印

declare -i j=0;for i in *.jpg; \
do magick $i -set option:watermarkWidth "%[fx:int(w*0.2)]" -alpha set -background none \( -fill "#FFFFFF80" -stroke "#FF000080" -strokeWidth 10 -undercolor "#00FF0070" -font 爱的目光无所不在.ttf -size "%[watermarkWidth]x" label:"这是水印" -gravity center -geometry +10+10  -rotate -25 \) -composite -quality 60 ${i:0:$[${#i}-4]}_wm.jpg; \
j=j+1;echo $j"."$i" convert succeed"!; done

添加图片水印

图片水印:按主图大小比例设置水印大小、设置水印透明度

magick nature.jpg -set option:logowidth "%[fx:int(w*0.25)]" \( logo.png -resize "%[logowidth]x" -background none -rotate -30 -channel A -fx "u*0.3" \) -gravity center -geometry +10+10 -composite result.jpg
  • -channel A -fx "u*0.3" 设置水印透明度(A通道就是alpha通道);

循环给当前目录下所有jpg图片添加水印

declare -i j=0;for i in *.jpg; \
do magick $i -set option:logowidth "%[fx:int(w*0.25)]" \
\( logo.png -resize "%[logowidth]x" -background none -rotate -30 -channel A -fx "u*0.3" \) -gravity center -geometry +10+10 -composite ${i:0:$[${#i}-4]}_wm.jpg; \
j=j+1;echo $j"."$i" convert succeed"!; done

参考:
后台使用imagemagick的convert命令来处理图片真是太方便了。
Anatomy of the Command-line
Why do some ImageMagick flags have plus sign (+) and others minus (-)?
Explanation for sprintf(“%03d”, 7) functionality?
ImageMagick命令
Watermarks
使用 ImageMagick 批量去水印

打赏
订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

0 评论
内联反馈
查看所有评论
Alex
Alex
2 年 前

test

0
希望看到您的想法,请您发表评论x

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

ImageMagick的基本使用