第06章 绘图与合成
第06章 绘图与合成
6.1 绘图基础
GraphicsMagick 的 -draw 参数使用类似 PostScript 的矢量绘图语法:
基本格式:
-draw "primitive 参数"
支持的绘图原语 (Primitives)
| 原语 | 说明 | 语法示例 |
|---|
point | 点 | point x,y |
line | 线段 | line x1,y1 x2,y2 |
rectangle | 矩形 | rectangle x1,y1 x2,y2 |
roundrectangle | 圆角矩形 | roundrectangle x1,y1 x2,y2 rx,ry |
circle | 圆形 | circle cx,cy ex,ey |
ellipse | 椭圆 | ellipse cx,cy rx,ry start,end |
arc | 弧线 | arc x1,y1 x2,y2 start,end |
polygon | 多边形 | polygon x1,y1 x2,y2 x3,y3 ... |
polyline | 折线 | polyline x1,y1 x2,y2 ... |
bezier | 贝塞尔曲线 | bezier x1,y1 x2,y2 x3,y3 ... |
path | SVG 路径 | path 'M0,0 L100,100' |
text | 文字 | text x,y 'Hello' |
image | 图像 | image Over x,y w,h file |
6.2 文字标注
6.2.1 基本文字绘制
# 基本文字
gm convert -font Helvetica -pointsize 36 \
-fill white -draw "text 50,50 'Hello World'" \
xc:'#333333' output.png
# 中文文字(需要中文字体)
gm convert -font "Noto-Sans-CJK-SC" -pointsize 48 \
-fill '#FFFFFF' -draw "text 30,60 '你好世界'" \
xc:'#2C3E50' output_cn.png
# 指定字体文件路径
gm convert -font /usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc \
-pointsize 32 -fill white \
-draw "text 20,40 '自定义字体'" \
xc:'#1a1a2e' output.png
6.2.2 文字排版参数
| 参数 | 说明 | 示例 |
|---|
-font | 字体名称或路径 | -font Arial |
-pointsize | 字号(磅值) | -pointsize 24 |
-fill | 文字颜色 | -fill '#FF0000' |
-stroke | 描边颜色 | -stroke black |
-strokewidth | 描边宽度 | -strokewidth 2 |
-gravity | 对齐方式 | -gravity center |
-interline-spacing | 行间距 | -interline-spacing 10 |
-kerning | 字间距 | -kerning 2 |
-style | 字体样式 | -style Italic |
-weight | 字体粗细 | -weight Bold |
-underline | 下划线 | -underline |
-encoding | 编码 | -encoding UTF-8 |
6.2.3 多行文字
# 方法 1:使用 \n
gm convert -font Helvetica -pointsize 24 \
-fill white -gravity center \
-draw "text 0,0 'Line 1\nLine 2\nLine 3'" \
xc:'#333' multiline.png
# 方法 2:使用 -annotate
gm convert -font Helvetica -pointsize 24 \
-fill white -gravity South \
-annotate +0+20 "底部居中文字" \
xc:'#333' annotate.png
6.2.4 文字特殊效果
# 阴影文字
gm convert -font Helvetica -pointsize 72 \
-fill '#333333' -draw "text 3,3 'Shadow'" \
-fill white -draw "text 0,0 'Shadow'" \
xc:'#2C3E50' shadow_text.png
# 描边文字
gm convert -font Helvetica -pointsize 72 \
-stroke black -strokewidth 3 -fill white \
-draw "text 0,0 'Outlined'" \
xc:'#3498DB' outlined_text.png
# 渐变文字效果(使用 mask)
gm convert -font Helvetica -pointsize 96 \
-fill white -annotate +0+0 'Gradient' \
gradient:'#FF6B6B'-'#4ECDC4' gradient_bg.png \
-composite gradient_text.png
6.2.5 业务场景:动态生成标题图
#!/bin/bash
# generate_title.sh — 动态生成博客标题图
# 用法: ./generate_title.sh "文章标题" "副标题"
TITLE="$1"
SUBTITLE="$2"
WIDTH=1200
HEIGHT=630
gm convert -size "${WIDTH}x${HEIGHT}" \
gradient:'#1a1a2e'-'#16213e' \
-font "Noto-Sans-CJK-SC" -pointsize 52 \
-fill '#E8E8E8' -gravity Center \
-annotate +0-40 "$TITLE" \
-pointsize 24 -fill '#AAAAAA' \
-annotate +0+30 "$SUBTITLE" \
"title_${WIDTH}x${HEIGHT}.png"
echo "标题图已生成: title_${WIDTH}x${HEIGHT}.png"
6.3 图形绘制
6.3.1 基本形状
# 矩形
gm convert -fill '#3498DB' -stroke white -strokewidth 2 \
-draw "rectangle 50,50 250,150" \
xc:'#2C3E50' rectangle.png
# 圆角矩形
gm convert -fill '#2ECC71' -stroke white -strokewidth 2 \
-draw "roundrectangle 50,50 250,150 15,15" \
xc:'#2C3E50' rounded_rect.png
# 圆形
gm convert -fill '#E74C3C' -stroke white -strokewidth 2 \
-draw "circle 150,150 150,50" \
xc:'#2C3E50' circle.png
# 椭圆
gm convert -fill '#9B59B6' -stroke white -strokewidth 2 \
-draw "ellipse 200,150 120,60 0,360" \
xc:'#2C3E50' ellipse.png
# 线段
gm convert -stroke '#F39C12' -strokewidth 3 \
-draw "line 50,50 350,250" \
xc:'#2C3E50' line.png
6.3.2 多边形
# 三角形
gm convert -fill '#1ABC9C' -stroke white -strokewidth 2 \
-draw "polygon 200,50 100,250 300,250" \
xc:'#2C3E50' triangle.png
# 五角星(使用路径)
gm convert -fill '#F1C40F' -stroke '#F39C12' -strokewidth 2 \
-draw "polygon 200,40 230,130 320,130 245,185 270,275 200,220 130,275 155,185 80,130 170,130" \
xc:'#2C3E50' star.png
6.3.3 绘图属性设置
# 设置不透明度
gm convert -fill 'rgba(255,0,0,0.5)' \
-draw "rectangle 50,50 250,150" \
xc:'#2C3E50' transparent_rect.png
# 设置线条虚线
gm convert -stroke white -strokewidth 2 \
-dasharray 10,5 \
-draw "line 50,50 350,250" \
xc:'#2C3E50' dashed_line.png
6.4 水印制作
6.4.1 文字水印
# 单行文字水印
gm convert photo.jpg \
-font Helvetica -pointsize 24 \
-fill 'rgba(255,255,255,0.5)' \
-gravity SouthEast -annotate +20+20 "© 2024 MySite" \
output_watermark.jpg
# 重复平铺水印
gm convert photo.jpg \
-font Helvetica -pointsize 48 \
-fill 'rgba(255,255,255,0.15)' \
-gravity Center -rotate 45 \
-annotate +0+0 "CONFIDENTIAL" \
output_tiled.jpg
6.4.2 图片水印
# 基本图片水印叠加
gm composite -dissolve 30 \
-gravity SouthEast -geometry +20+20 \
watermark.png photo.jpg output.jpg
# 平铺水印
gm composite -dissolve 15 \
-tile watermark.png photo.jpg output.jpg
# 居中水印
gm composite -dissolve 40 \
-gravity Center \
watermark.png photo.jpg output.jpg
6.4.3 水印参数说明
| 参数 | 说明 | 示例 |
|---|
-dissolve N | 透明度 (0-100) | -dissolve 30 = 30% 不透明 |
-gravity | 位置锚点 | -gravity SouthEast |
-geometry +X+Y | 偏移量 | -geometry +20+20 |
-tile | 平铺模式 | -tile |
-watermark N% | 水印强度 | -watermark 30% |
-compose | 合成模式 | -compose Over |
6.4.4 业务场景:批量添加水印
#!/bin/bash
# batch_watermark.sh
# 批量为目录中的图片添加水印
WATERMARK="watermark.png"
INPUT_DIR="input/"
OUTPUT_DIR="watermarked/"
DISSOLVE=30
mkdir -p "$OUTPUT_DIR"
for img in "$INPUT_DIR"*.{jpg,jpeg,png}; do
[ -f "$img" ] || continue
filename=$(basename "$img")
echo "处理: $filename"
gm composite -dissolve "$DISSOLVE" \
-gravity SouthEast -geometry +20+20 \
"$WATERMARK" "$img" \
"$OUTPUT_DIR$filename"
done
echo "批量水印完成!共处理 $(ls "$OUTPUT_DIR" | wc -l) 张图片"
6.5 图像合成 (Composite)
6.5.1 合成模式 (Compose Operators)
| 模式 | 说明 | 典型用途 |
|---|
Over | 覆盖(默认) | 叠加图层 |
In | 交集(仅重叠部分) | 蒙版效果 |
Out | 差集(仅非重叠部分) | 镂空效果 |
Atop | 在上面(含背景) | 合成 |
Xor | 异或 | 特殊效果 |
Plus | 相加 | 亮度叠加 |
Minus | 相减 | 差异检测 |
Multiply | 正片叠底 | 加深效果 |
Screen | 滤色 | 减淡效果 |
Overlay | 叠加 | 增强对比 |
Dissolve | 溶解 | 半透明叠加 |
Modulate | 调制 | 亮度调整 |
CopyOpacity | 复制透明度 | 蒙版 |
Difference | 差值 | 图像对比 |
Hue | 色相 | 颜色替换 |
Saturation | 饱和度 | 颜色调整 |
Colorize | 着色 | 色彩叠加 |
6.5.2 合成示例
# 基本叠加
gm composite overlay.png base.jpg output.jpg
# 使用指定合成模式
gm composite -compose Multiply overlay.png base.jpg output.jpg
# 使用蒙版(透明度)
gm composite -compose CopyOpacity mask.png base.jpg output.png
# 差异对比(找不同)
gm composite -compose Difference img1.jpg img2.jpg diff.jpg
6.5.3 双图合成场景
# 场景:前后对比图
gm montage -label "Before" before.jpg \
-label "After" after.jpg \
-tile 2x1 -geometry 600x400+5+5 \
-background '#333' comparison.jpg
# 场景:A/B 测试对比
gm convert before.jpg after.jpg +append comparison.jpg
6.6 图像拼接与画布操作
6.6.1 创建画布
# 纯色画布
gm convert -size 800x600 xc:'#2C3E50' canvas.png
# 透明画布
gm convert -size 800x600 xc:none canvas_transparent.png
# 渐变画布
gm convert -size 800x600 gradient:'#FF6B6B'-'#4ECDC4' gradient_canvas.png
# 径向渐变
gm convert -size 800x600 \
radial-gradient:'#FFFFFF'-'#000000' \
radial_canvas.png
6.6.2 多图拼接
# 水平拼接(相同高度)
gm convert img1.jpg img2.jpg img3.jpg +append horizontal.jpg
# 垂直拼接(相同宽度)
gm convert img1.jpg img2.jpg img3.jpg -append vertical.jpg
# 网格拼接(使用 montage)
gm montage -tile 3x2 -geometry 300x200+5+5 \
-background '#222' *.jpg grid.jpg
# 带标题的网格
gm montage -label '%f' -tile 3x2 \
-geometry 300x200+5+5 \
-background '#222' -fill white \
*.jpg titled_grid.jpg
6.7 图层操作
6.7.1 使用 -page 控制图层位置
# 将图像放置在指定位置
gm convert \
-size 800x600 xc:'#2C3E50' \
-page +50+50 small_img1.jpg \
-page +400+300 small_img2.jpg \
-layers merge output.jpg
6.7.2 平铺背景
# 创建重复平铺图案
gm convert -size 100x100 \
-fill '#3498DB' -draw "rectangle 0,0 50,50" \
-fill '#2980B9' -draw "rectangle 50,50 100,100" \
pattern_tile.png
# 平铺为背景
gm convert pattern_tile.png -resize 800x600! tiled_bg.png
6.8 注解与标签
6.8.1 -annotate 参数
# annotate 基本用法
# -annotate X旋转xY旋转 +X偏移+Y偏移 "文字"
# 无旋转,偏移 (0,0)
gm convert -font Helvetica -pointsize 36 -fill white \
-annotate +0+0 "Center Text" \
xc:'#333' annotated.png
# 旋转 45 度
gm convert -font Helvetica -pointsize 36 -fill white \
-annotate 45x45+0+0 "Rotated" \
xc:'#333' rotated_text.png
# 使用 gravity 定位
gm convert -font Helvetica -pointsize 24 -fill white \
-gravity NorthWest -annotate +20+20 "Top Left" \
-gravity SouthEast -annotate +20+20 "Bottom Right" \
xc:'#333' corner_text.png
6.8.2 自动编号标注
#!/bin/bash
# label_images.sh — 为图片批量添加编号标签
OUTPUT_DIR="labeled/"
mkdir -p "$OUTPUT_DIR"
i=1
for img in *.jpg; do
[ -f "$img" ] || continue
gm convert "$img" \
-fill 'rgba(0,0,0,0.6)' \
-draw "rectangle 0,0 60,30" \
-font Helvetica -pointsize 18 -fill white \
-gravity NorthWest -annotate +10+5 "#${i}" \
"$OUTPUT_DIR$img"
((i++))
done
6.9 高级合成技巧
6.9.1 圆形头像
# 创建圆形裁剪蒙版
gm convert -size 200x200 \
xc:none -fill white \
-draw "circle 100,100 100,0" \
mask_circle.png
# 应用蒙版
gm convert input.jpg -resize 200x200! +profile '*' /tmp/resized.jpg
gm composite -compose CopyOpacity mask_circle.png /tmp/resized.jpg avatar.png
# 添加圆形边框
gm convert avatar.png \
-bordercolor none -border 4 \
\( -size 208x208 xc:none -fill none \
-stroke '#3498DB' -strokewidth 4 \
-draw "circle 104,104 104,0" \) \
-composite avatar_bordered.png
6.9.2 图片倒影效果
#!/bin/bash
# reflection.sh — 生成图片倒影效果
INPUT="$1"
OUTPUT="reflection_$(basename $INPUT)"
# 获取尺寸
W=$(gm identify -format "%w" "$INPUT")
H=$(gm identify -format "%h" "$INPUT")
REFLECT_H=$((H / 3))
TOTAL_H=$((H + REFLECT_H + 10))
# 创建倒影
gm convert "$INPUT" \
-flip -resize "${W}x${REFLECT_H}!" \
-level 0%,100%,0.5 \
/tmp/reflection.png
# 合成
gm convert -size "${W}x${TOTAL_H}" xc:'#2C3E50' \
"$INPUT" -geometry +0+0 -composite \
/tmp/reflection.png -geometry +0+${H} -composite \
"$OUTPUT"
rm -f /tmp/reflection.png
echo "倒影效果已生成: $OUTPUT"
6.10 绘图操作速查表
| 操作 | 命令 |
|---|
| 矩形 | -draw "rectangle x1,y1 x2,y2" |
| 圆形 | -draw "circle cx,cy ex,ey" |
| 线段 | -draw "line x1,y1 x2,y2" |
| 文字 | -draw "text x,y 'text'" |
| 水印 | -annotate +X+Y "text" |
| 图片叠加 | gm composite overlay base output |
| 平铺叠加 | gm composite -tile overlay base output |
| 水平拼接 | gm convert a.jpg b.jpg +append out.jpg |
| 垂直拼接 | gm convert a.jpg b.jpg -append out.jpg |
| 创建画布 | -size WxH xc:COLOR |
| 渐变画布 | -size WxH gradient:c1-c2 |
6.11 本章小结
| 要点 | 说明 |
|---|
-draw 是绘图核心 | 支持矩形、圆形、多边形、文字等 |
文字标注用 -annotate | 更灵活的定位和旋转 |
水印用 gm composite | 支持 dissolve 透明度和 tile 平铺 |
| 合成模式丰富 | Over、Multiply、Screen 等 |
| 蒙版实现裁剪效果 | CopyOpacity 模式 |
| 中文需要 CJK 字体 | 确保安装了中文字体包 |
扩展阅读
- GraphicsMagick Draw 命令参考
- GraphicsMagick Composite 参考
- SVG Path 语法
- 图像合成模式详解
- CSS Blend Modes(类比理解)
上一章:第05章 颜色处理
下一章:第07章 图像特效