翻转(Flip)、画布扩展(Embed)与多图网格拼接
除了缩放和裁剪,画布几何操作还包括三项高频任务:镜像翻转(Flip / Flop)、将图像嵌入更大画布并填充四周(Embed / Extend / Gravity),以及将多张图像拼接为长图或网格(Join / ArrayJoin)。


1. 水平与垂直翻转(注意 sharp 的命名差异)
Section titled “1. 水平与垂直翻转(注意 sharp 的命名差异)”在 libvips 底层,翻转由 vips_flip(direction) 完成,方向枚举为 horizontal(左右镜像)与 vertical(上下镜像)。
// 水平翻转(左右镜像):支持 AccessSequentialif err := image.Flip(vips.DirectionHorizontal); err != nil { return err}
// 垂直翻转(上下镜像):需要随机访问或预先实体化缓冲if err := image.Flip(vips.DirectionVertical); err != nil { return err}import sharp from 'sharp';
// flop() = 水平翻转(左右镜像)await sharp('input.jpg').flop().webp({ quality: 82 }).toFile('flip-horizontal.webp');
// flip() = 垂直翻转(上下镜像)await sharp('input.jpg').flip().webp({ quality: 82 }).toFile('flip-vertical.webp');import pyvips
image = pyvips.Image.new_from_file("input.jpg")horiz = image.fliphor() # 等同于 image.flip("horizontal")vert = image.flipver() # 等同于 image.flip("vertical")horiz.write_to_file("flip-horizontal.webp", Q=82)vips flip input.jpg 'flip-horizontal.webp[Q=82]' horizontalvips flip input.jpg 'flip-vertical.webp[Q=82]' vertical2. 画布扩展与边缘延展模式(Embed / Gravity / extend)
Section titled “2. 画布扩展与边缘延展模式(Embed / Gravity / extend)”当需要为图片四周加上固定像素的内边距(Padding),或者把横图放进正方形画布且不裁切原图(Letterboxing / Fit Contain)时,使用 vips_embed 或 vips_gravity。
libvips 支持 6 种填充新增画布区域的扩展策略(VipsExtend):
| 扩展策略 | govips vips.ExtendStrategy |
sharp extendWith |
pyvips / vips CLI extend |
填充效果 |
|---|---|---|---|---|
| 黑色填充 | vips.ExtendBlack |
'background'(默认黑) |
"black" |
新增像素全为 0 |
| 白色填充 | vips.ExtendWhite |
'background'(配白底) |
"white" |
新增像素全为最大值 |
| 指定背景色 | EmbedBackground / EmbedBackgroundRGBA |
'background' + background |
"background" + background=[...] |
使用自定义 RGB/RGBA 填充 |
| 边缘像素复制拉伸 | vips.ExtendCopy |
'copy' |
"copy" |
重复原图最外侧一圈像素 |
| 镜像反射延展 | vips.ExtendMirror |
'mirror' |
"mirror" |
像镜子一样反射边缘画面 |
| 平铺重复 | vips.ExtendRepeat |
'repeat' |
"repeat" |
将整张原图周期性重复平铺 |
// 方式 A:四周各扩充 40px 白边,总尺寸变为 (W+80)×(H+80)w, h := image.Width(), image.Height()bg := &vips.Color{R: 248, G: 250, B: 252}if err := image.EmbedBackground(40, 40, w+80, h+80, bg); err != nil { return err}
// 方式 B:使用镜像边缘延展 (ExtendMirror)if err := image.Embed(40, 40, w+80, h+80, vips.ExtendMirror); err != nil { return err}import sharp from 'sharp';
// 四周扩充 40px,使用自定义背景色或 extendWith: 'mirror' | 'copy' | 'repeat'await sharp('input.jpg') .extend({ top: 40, bottom: 40, left: 40, right: 40, extendWith: 'background', background: { r: 248, g: 250, b: 252 }, }) .webp({ quality: 82 }) .toFile('padded.webp');import pyvips
image = pyvips.Image.new_from_file("input.jpg")padded = image.embed( 40, 40, image.width + 80, image.height + 80, extend="background", background=[248, 250, 252],)padded.write_to_file("padded.webp", Q=82)W=$(vipsheader -f width input.jpg)H=$(vipsheader -f height input.jpg)vips embed input.jpg 'padded.webp[Q=82]' 40 40 $((W + 80)) $((H + 80)) \ --extend background --background 248,250,2523. 多图拼接与网格拼图(Join / ArrayJoin)
Section titled “3. 多图拼接与网格拼图(Join / ArrayJoin)”当需要把两张图水平/垂直拼接成长图,或把一组缩略图排列成 N 列的雪碧图(Sprite Sheet)/ 宫格图时,使用 join 与 arrayjoin:
// 1. 两图水平或垂直拼接 (Join)if err := leftImg.Join(rightImg, vips.DirectionHorizontal); err != nil { return err}
// 2. 多图按每行 2 列排列为网格 (ArrayJoin)if err := tile1.ArrayJoin([]*vips.ImageRef{tile2, tile3, tile4}, 2); err != nil { return err}import sharp from 'sharp';
// sharp 支持传入图像数组与 join 构造选项(across 指定每行张数,shim 指定间距)await sharp(['tile1.webp', 'tile2.webp', 'tile3.webp', 'tile4.webp'], { join: { across: 2, shim: 8, background: { r: 29, g: 45, b: 53 }, },}) .webp({ quality: 82 }) .toFile('grid.webp');import pyvips
tiles = [pyvips.Image.new_from_file(f"tile{i}.webp") for i in range(1, 5)]grid = pyvips.Image.arrayjoin(tiles, across=2, shim=8, background=[29, 45, 53])grid.write_to_file("grid.webp", Q=82)vips arrayjoin "tile1.webp tile2.webp tile3.webp tile4.webp" 'grid.webp[Q=82]' \ --across 2 --shim 8 --background 29,45,53