强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第06章 绘图与合成

第06章 绘图与合成

6.1 绘图基础

GraphicsMagick 的 -draw 参数使用类似 PostScript 的矢量绘图语法:

基本格式:
-draw "primitive 参数"

支持的绘图原语 (Primitives)

原语说明语法示例
pointpoint 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 ...
pathSVG 路径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 字体确保安装了中文字体包

扩展阅读

  1. GraphicsMagick Draw 命令参考
  2. GraphicsMagick Composite 参考
  3. SVG Path 语法
  4. 图像合成模式详解
  5. CSS Blend Modes(类比理解)

上一章第05章 颜色处理 下一章第07章 图像特效