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

GraphicsMagick 图像处理完整教程 / 第04章 几何变换

第04章 几何变换

4.1 几何参数语法

GraphicsMagick 使用统一的 Geometry 字符串 来描述尺寸、位置和偏移量:

标准格式:[WxH][+X+Y][!@%<>^]

W  — 宽度
H  — 高度
X  — X 偏移
Y  — Y 偏移
!  — 强制忽略宽高比
@  — 按像素总数缩放
%  — 按百分比缩放
>  — 仅缩小(大于目标尺寸时)
<  — 仅放大(小于目标尺寸时)
^  — 填充裁剪(保证覆盖目标区域)

Geometry 示例

表达式含义
800宽度 800,高度按比例
x600高度 600,宽度按比例
800x600限制在 800×600 范围内,保持比例
800x600!强制缩放到 800×600(可能变形)
800x600>仅当原图大于 800×600 时缩放
800x600<仅当原图小于 800×600 时放大
800x600^保证覆盖 800×600 区域(可能超出)
800x600+100+50800×600,偏移 (100,50)
50%缩放到 50%
120000@缩放到约 120000 像素总数

4.2 缩放 (Resize)

4.2.1 基本缩放

# 按宽度缩放(高度自动计算)
gm convert -resize 800 input.jpg output.jpg

# 按高度缩放
gm convert -resize x600 input.jpg output.jpg

# 按百分比缩放
gm convert -resize 50% input.jpg output.jpg
gm convert -resize 200% input.jpg output.jpg

# 指定最大范围(保持比例)
gm convert -resize "800x600" input.jpg output.jpg

4.2.2 缩放模式详解

# 模式 1:保持比例,限制最大尺寸
# 原图 1920x1080 → 输出 800x450
gm convert -resize "800x600" input.jpg output.jpg

# 模式 2:强制指定尺寸(可能变形)
# 原图 1920x1080 → 输出 800x600(拉伸)
gm convert -resize "800x600!" input.jpg output.jpg

# 模式 3:仅缩小(大于目标时才处理)
# 原图 1920x1080 → 输出 800x450(缩小)
# 原图 400x300  → 输出 400x300(不变)
gm convert -resize "800x600>" input.jpg output.jpg

# 模式 4:仅放大(小于目标时才处理)
# 原图 400x300  → 放大到 800x600
# 原图 1920x1080 → 不变
gm convert -resize "800x600<" input.jpg output.jpg

# 模式 5:填充裁剪(保证覆盖目标区域,可能裁掉边缘)
# 原图 1920x1080 (16:9) → 目标 800x600 (4:3)
# 先缩放到 1067x600(覆盖 800x600),再裁掉多余部分
gm convert -resize "800x600^" \
  -gravity center -extent "800x600" \
  input.jpg output.jpg

4.2.3 缩放质量与滤波器

# 默认使用 Lanczos 滤波器(高质量)

# 指定不同的插值滤波器
gm convert -filter Lanczos -resize 50% input.jpg output.jpg
gm convert -filter Mitchell -resize 50% input.jpg output.jpg
gm convert -filter Catrom -resize 50% input.jpg output.jpg
gm convert -filter Gaussian -resize 50% input.jpg output.jpg
gm convert -filter Box -resize 50% input.jpg output.jpg
gm convert -filter Point -resize 50% input.jpg output.jpg
滤波器质量速度适用场景
Lanczos⭐⭐⭐⭐⭐高质量缩放(默认)
Mitchell⭐⭐⭐⭐平滑缩小
Catrom⭐⭐⭐⭐锐利缩小
Gaussian⭐⭐⭐模糊缩放效果
Box⭐⭐快速缩小(整数倍)
Point最快像素艺术(最近邻)
Sinc⭐⭐⭐⭐⭐最慢理论最优(振铃效应)

4.2.4 业务场景:Web 响应式图片

#!/bin/bash
# generate_responsive.sh
# 为响应式 Web 设计生成多尺寸图片

INPUT="$1"
BASENAME=$(basename "${INPUT%.*}")

# 响应式断点
declare -A BREAKPOINTS=(
  ["xs"]="480"    # 手机
  ["sm"]="768"    # 平板竖屏
  ["md"]="1024"   # 平板横屏
  ["lg"]="1440"   # 桌面
  ["xl"]="1920"   # 大屏
)

for name in "${!BREAKPOINTS[@]}"; do
  width="${BREAKPOINTS[$name]}"
  gm convert "$INPUT" \
    -filter Lanczos \
    -resize "${width}>" \
    -quality 85 \
    -strip \
    "output_${BASENAME}_${name}.jpg"
  size=$(gm identify -format "%b" "output_${BASENAME}_${name}.jpg")
  echo "${name} (${width}px): ${size}"
done

4.3 裁剪 (Crop)

4.3.1 基本裁剪

# 从左上角 (0,0) 裁剪 400x300 区域
gm convert -crop 400x300+0+0 input.jpg output.jpg

# 从指定位置开始裁剪
gm convert -crop 400x300+100+50 input.jpg output.jpg

# 从中心裁剪
gm convert -gravity center -crop 400x300+0+0 input.jpg output.jpg

4.3.2 Gravity 锚点

-gravity 参数设置裁剪的参考锚点:

NorthWest (左上)    North (上)    NorthEast (右上)
West (左)           Center (中)   East (右)
SouthWest (左下)    South (下)    SouthEast (右下)
# 从右下角裁剪
gm convert -gravity SouthEast -crop 200x200+0+0 input.jpg output.jpg

# 从顶部中心裁剪(适合人像去底部)
gm convert -gravity North -crop 800x400+0+0 portrait.jpg output.jpg

4.3.3 自动裁剪

# 自动去除边缘空白/纯色边框
gm convert -trim input.jpg output.jpg

# 带容差的 trim(允许颜色微小差异)
gm convert -fuzz 5% -trim input.jpg output.jpg

# 增加 trim 后的边距
gm convert -trim +repage -bordercolor white -border 20 input.jpg output.jpg

4.3.4 业务场景:智能裁剪头像

#!/bin/bash
# crop_avatar.sh — 将照片裁剪为正方形头像
# 用法: ./crop_avatar.sh input.jpg 200

INPUT="$1"
SIZE="${2:-200}"

# 获取原始尺寸
WH=$(gm identify -format "%wx%h" "$INPUT")
W=$(echo $WH | cut -dx -f1)
H=$(echo $WH | cut -dx -f2)

# 计算裁剪区域(取短边为基准)
if [ "$W" -gt "$H" ]; then
  OFFSET=$(( (W - H) / 2 ))
  CROP="${H}x${H}+${OFFSET}+0"
else
  OFFSET=$(( (H - W) / 2 ))
  CROP="${W}x${W}+0+${OFFSET}"
fi

gm convert "$INPUT" \
  -crop "$CROP" \
  -resize "${SIZE}x${SIZE}!" \
  -quality 90 \
  "avatar_${SIZE}.jpg"

echo "已生成 ${SIZE}x${SIZE} 头像: avatar_${SIZE}.jpg"

4.4 旋转 (Rotate)

4.4.1 基本旋转

# 顺时针旋转 90°
gm convert -rotate 90 input.jpg output.jpg

# 旋转 180°(倒置)
gm convert -rotate 180 input.jpg output.jpg

# 逆时针旋转 90°(即 270°)
gm convert -rotate 270 input.jpg output.jpg
gm convert -rotate "-90" input.jpg output.jpg

# 自由角度旋转
gm convert -rotate 30 input.jpg output.jpg

4.4.2 旋转与背景色

自由角度旋转后,空白区域会填充背景色:

# 默认黑色背景
gm convert -rotate 30 input.jpg output.jpg

# 指定白色背景
gm convert -background white -rotate 30 input.jpg output.jpg

# 透明背景(需要 PNG 格式)
gm convert -background none -rotate 30 input.jpg output.png

# 指定任意颜色
gm convert -background '#FF6B6B' -rotate 45 input.jpg output.jpg

4.4.3 自动旋转(EXIF 方向)

数码相机拍摄的照片通常包含 EXIF 方向标记:

# 根据 EXIF 信息自动校正方向
gm convert -auto-orient input.jpg output.jpg

# 查看 EXIF 方向
gm identify -verbose input.jpg | grep -i "orientation"
EXIF 方向值含义需要的操作
1正常
2水平翻转-flop
3旋转 180°-rotate 180
4垂直翻转-flip
5顺时针 90° + 水平翻转-rotate 90 -flop
6顺时针 90°-rotate 90
7逆时针 90° + 水平翻转-rotate -90 -flop
8逆时针 90°-rotate -90

4.5 翻转 (Flip & Flop)

# 垂直翻转(上下颠倒)
gm convert -flip input.jpg output.jpg

# 水平翻转(左右镜像)
gm convert -flop input.jpg output.jpg

# 同时翻转(等价于旋转 180°)
gm convert -flip -flop input.jpg output.jpg

4.6 扩展与填充 (Extent & Border)

4.6.1 Extent — 扩展画布

# 扩展画布到指定大小(锚点控制方向)
# 在底部添加空白
gm convert -gravity North -extent 800x1000 \
  -background white input.jpg output.jpg

# 居中扩展,四周添加边距
gm convert -gravity center -extent 1000x800 \
  -background '#f0f0f0' input.jpg output.jpg

4.6.2 Border — 添加边框

# 添加 10px 灰色边框
gm convert -border 10 -bordercolor gray input.jpg output.jpg

# 不对称边框
gm convert -border 20x10 -bordercolor black input.jpg output.jpg
# 20x10 表示左右各20px,上下各10px

4.7 仿射变换 (Affine Transform)

仿射变换包括缩放、旋转、剪切和平移的组合:

# 使用 -affine 和 -transform 进行仿射变换
# 参数: sx rx ry sy tx ty
# sx,sy — 缩放因子
# rx,ry — 旋转/剪切因子
# tx,ty — 平移量

# 示例:缩放 + 旋转
gm convert \
  -affine 0.866,0.5,-0.5,0.866,0,0 \
  -transform input.jpg output.jpg

# 示例:水平剪切 (Shear)
gm convert -shear 30x0 input.jpg output.jpg

# 示例:垂直剪切
gm convert -shear 0x30 input.jpg output.jpg

# 示例:同时水平和垂直剪切
gm convert -shear 20x15 input.jpg output.jpg

4.8 透视变换 (Perspective)

透视变换可以校正拍摄角度导致的变形:

# 使用 -distort Perspective 进行透视校正
# 需要指定 4 个源点和 4 个目标点

# 示例:校正倾斜拍摄的文档
gm convert \
  -distort Perspective \
  "0,0 50,10  300,0 280,30  300,400 290,380  0,400 30,390" \
  input.jpg output.jpg

# Point 格式:src_x,src_y dst_x,dst_y
# 四个角的映射关系

透视变换参数说明

原始图四个角          目标图四个角
(0,0)──────(W,0)  →  (x1,y1)──────(x2,y2)
  │          │          │            │
  │          │          │            │
(0,H)──────(W,H)  →  (x3,y3)──────(x4,y4)

4.9 卷曲与变形 (Distort)

GraphicsMagick 支持多种 distortion(扭曲)模式:

# 查看支持的 distort 方法
gm convert -list distort

# Barrel 桶形畸变校正
gm convert -virtual-pixel edge \
  -distort Barrel "0.1 0.0 0.0 1.0" \
  input.jpg output.jpg

# BarrelInverse 枕形畸变
gm convert -virtual-pixel edge \
  -distort BarrelInverse "0.1 0.0 0.0 1.0" \
  input.jpg output.jpg

4.10 综合实战

场景:电商商品图片标准化

#!/bin/bash
# product_standardize.sh
# 电商商品图片标准化处理

INPUT="$1"
OUTPUT_DIR="product_output"
mkdir -p "$OUTPUT_DIR"

BASENAME=$(basename "${INPUT%.*}")

echo "处理: $INPUT"

# 步骤 1:自动旋转(EXIF 校正)
gm convert -auto-orient "$INPUT" /tmp/oriented.jpg

# 步骤 2:智能裁剪为正方形
WH=$(gm identify -format "%wx%h" /tmp/oriented.jpg)
W=$(echo $WH | cut -dx -f1)
H=$(echo $WH | cut -dx -f2)
if [ "$W" -gt "$H" ]; then
  gm convert -gravity center -crop "${H}x${H}+0+0" +repage \
    /tmp/oriented.jpg /tmp/cropped.jpg
else
  gm convert -gravity center -crop "${W}x${W}+0+0" +repage \
    /tmp/oriented.jpg /tmp/cropped.jpg
fi

# 步骤 3:生成多种尺寸
for size in 400 800 1200; do
  gm convert /tmp/cropped.jpg \
    -filter Lanczos \
    -resize "${size}x${size}!" \
    -quality 90 \
    -strip \
    -background white \
    -gravity center \
    -extent "${size}x${size}" \
    "$OUTPUT_DIR/${BASENAME}_${size}.jpg"
  echo "  ✅ ${size}x${size} 已生成"
done

# 清理临时文件
rm -f /tmp/oriented.jpg /tmp/cropped.jpg

echo "完成!文件输出到 $OUTPUT_DIR/"

4.11 变换操作速查表

操作命令说明
等比缩放-resize 800按宽度等比
百分比缩放-resize 50%按百分比
强制尺寸-resize 800x600!可能变形
仅缩小-resize 800x600>大于才缩
仅放大-resize 800x600<小于才放
填充裁剪-resize 800x600^ + -extent覆盖后裁
固定裁剪-crop 400x300+X+Y区域裁剪
居中裁剪-gravity center -crop 400x300+0+0中心裁
自动去边-trim去纯色边
旋转-rotate 90顺时针度数
EXIF 旋转-auto-orient自动校正
垂直翻转-flip上下颠倒
水平翻转-flop左右镜像
剪切-shear 30x0水平剪切
扩展画布-extent WxH扩展到
添加边框-border NN像素边框

4.12 本章小结

要点说明
Geometry 字符串是核心语法WxH+X+Y!@%<>^
>< 很常用Web 图片处理中避免放大很重要
-gravity 控制锚点裁剪/扩展时至关重要
-auto-orient 处理手机照片几乎所有上传处理都应加上
-resize 选对滤波器Lanczos 是默认高质量选择
仿射/透视变换更高级文档校正、畸变校正等场景

扩展阅读

  1. GraphicsMagick Geometry 详解
  2. 图像插值算法对比
  3. 透视变换数学原理
  4. EXIF Orientation 标准
  5. Lanczos 采样算法

上一章第03章 基本操作 下一章第05章 颜色处理