Skip to content

Flip, canvas embed/extend, and multi-image grid join

Copy page

Beyond resizing and cropping, canvas geometry covers three frequent production tasks: mirroring images (Flip / Flop), embedding an image inside a larger padded canvas (Embed / Extend / Gravity), and stitching multiple images into strips or grids (Join / ArrayJoin).

1938×1292 Gate of the Orient night photograph used for flip and canvas operations
Input photograph: JPEG1938 × 1292
Horizontally mirrored 1938×1292 Gate of the Orient night photograph
Horizontal mirror: WebP1938 × 1292 (govips reference output)

1. Horizontal and vertical flips (watch sharp’s naming)

Section titled “1. Horizontal and vertical flips (watch sharp’s naming)”

In libvips, mirroring is performed by vips_flip(direction) with horizontal (left-right mirror) or vertical (top-bottom mirror).

// Horizontal mirror (left-right): compatible with AccessSequential
if err := image.Flip(vips.DirectionHorizontal); err != nil {
return err
}
// Vertical mirror (top-bottom): requires random access or prior materialization
if err := image.Flip(vips.DirectionVertical); err != nil {
return err
}

2. Canvas padding and edge extension modes (Embed / Gravity / extend)

Section titled “2. Canvas padding and edge extension modes (Embed / Gravity / extend)”

To add fixed padding around an image or letterbox a landscape photo inside a square canvas without cropping, use vips_embed or vips_gravity.

libvips supports six edge-extension strategies (VipsExtend) for filling the newly exposed canvas area:

Extension strategy govips vips.ExtendStrategy sharp extendWith pyvips / vips CLI extend Visual effect
Black fill vips.ExtendBlack 'background' (default black) "black" New pixels are all zero
White fill vips.ExtendWhite 'background' (with white) "white" New pixels are all maximum
Custom background colour EmbedBackground / EmbedBackgroundRGBA 'background' + background "background" + background=[...] Fills with custom RGB/RGBA
Edge clamping vips.ExtendCopy 'copy' "copy" Repeats the outermost border pixels
Mirror reflection vips.ExtendMirror 'mirror' "mirror" Reflects the image across each edge
Periodic tiling vips.ExtendRepeat 'repeat' "repeat" Tiles the entire image repeatedly
// Option A: Pad 40px on all four sides with a custom background colour
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
}
// Option B: Pad 40px using mirror edge reflection (ExtendMirror)
if err := image.Embed(40, 40, w+80, h+80, vips.ExtendMirror); err != nil {
return err
}

3. Multi-image stitching and grid layout (Join / ArrayJoin)

Section titled “3. Multi-image stitching and grid layout (Join / ArrayJoin)”

To stitch two images side by side or vertically, or to arrange an array of thumbnails into an N-column sprite sheet or contact grid, use join and arrayjoin:

// 1. Two-image horizontal or vertical join
if err := leftImg.Join(rightImg, vips.DirectionHorizontal); err != nil {
return err
}
// 2. Multi-image grid layout with 2 columns per row (ArrayJoin)
if err := tile1.ArrayJoin([]*vips.ImageRef{tile2, tile3, tile4}, 2); err != nil {
return err
}