libvips is a streaming image-processing library tuned for large and many images: low memory, partial reads, parallel pipelines. Where ImageMagick loads each image fully into RAM, libvips streams pixels through the operations it actually needs. At ~1k+ images or for any image bigger than a few hundred MB, it's the right tool. Bundled here under installMediaTools=true together with ffmpeg, ImageMagick, and ExifTool.
- Install:
- macOS — Homebrew (
brew install vips), managed bydot_ansible/roles/media_tools/tasks/main.ymlwheninstallMediaTools=true. - Linux — apt (
sudo apt install libvips-tools), same role / same flag. The-toolspackage ships the CLIs (vips,vipsthumbnail,vipsedit,vipsheader); the barelibvips42package is library-only.
- macOS — Homebrew (
- Verify:
vips --versionandvipsthumbnail --version. - Status in this repo: opt-in via
installMediaTools=true. No automation calls into it yet — it's there for when ImageMagick chokes.
| Situation | Pick |
|---|---|
| Single image, complex composite / annotate | ImageMagick |
| One-off resize / crop | Either; ImageMagick is more familiar |
| Batch of 1k+ images | libvips (often 5–10× faster, 1/10 the RAM) |
| Image > 500 MB / gigapixel scans | libvips (ImageMagick may OOM) |
| Server-side thumbnail pipeline | libvips (vipsthumbnail is purpose-built) |
| Interactive ad-hoc tweaks | ImageMagick (better one-liners) |
The two complement each other — having both installed is the default here.
Generate thumbnails from large images without ever loading the full pixel buffer:
# Single image — max 1280px on the long edge
vipsthumbnail input.jpg --size 1280 -o output.jpg
# Pin a width (height auto)
vipsthumbnail input.jpg --size '1280x'
# Pin a height (width auto)
vipsthumbnail input.jpg --size 'x720'
# Output template — write next to source as <name>_tn.jpg
vipsthumbnail *.jpg --size 320 -o '%s_tn.jpg'
# Custom output dir
vipsthumbnail *.jpg --size 320 -o 'thumbs/%s.jpg[Q=85]'%s in the output template expands to the input basename (without extension). The [Q=85] suffix sets JPEG quality.
For raw camera files / TIFFs / WebP / HEIC — vipsthumbnail picks the right loader automatically and only decodes the region needed for the target size.
# Resize (preserves aspect)
vips resize input.jpg output.jpg 0.5 # half size
# Crop — left, top, width, height
vips crop input.jpg output.jpg 100 50 800 600
# Rotate
vips rot input.jpg output.jpg d90 # 90° clockwise; d180 / d270
# Flip
vips flip input.jpg output.jpg horizontal
# Strip ICC + metadata on save (smaller files)
vips copy input.jpg output.jpg[strip,Q=85]Saver options (Q=..., strip, interlace, optimize_coding, subsample_mode=...) go in [brackets] after the output path. Loaders use the same syntax (input.tif[page=2] for multi-page TIFFs).
# JPEG with custom quality
vips copy input.png output.jpg[Q=80,optimize_coding,strip]
# WebP (smaller, modern)
vips copy input.png output.webp[Q=80,strip,effort=4]
# AVIF (smallest, slowest encode)
vips copy input.png output.avif[Q=50,effort=6]
# Tiled / pyramid TIFF (zoomable on viewers like OpenSeadragon)
vips copy input.jpg output.tif[tile,pyramid,compression=jpeg,Q=85]vips --vips-help-loaders and --vips-help-savers enumerate the full list.
vipsheader input.jpg # one-line header
vipsheader -a input.jpg # all tags
vipsheader -f width input.jpg # single field
vipsheader -f vips-loader input.jpg # which loader was pickedlibvips' streaming model means pipelines stay memory-bounded:
# Resize then jpeg → smaller file, never loads full image
vips resize input.tif output.jpg[Q=85] 0.25
# Sequential mode for huge files — reads top-to-bottom, can't seek backwards
vipsthumbnail huge_scan.tif --size 2000 -o thumb.jpg --intent perceptualFor Python (and other binding) usage see https://www.libvips.org/API/current/python.html. The CLI covers most batch needs.
- No
convert input output— every operation has a verb (resize,crop,rot, …). Runvips list classesto enumerate. - Saver options live in brackets —
output.jpg Q=85does not work;output.jpg[Q=85]does. Easy to miss. - Color profiles — by default vips preserves embedded ICC profiles. Pass
[strip]if downstream consumers don't handle them, or convert withvips icc_transformfirst. - Sequential mode lock-in —
--intent perceptualetc. onvipsthumbnailswitch to streaming mode. Random-access ops like center crop won't work in that mode; usevipsfor those.
- ImageMagick — the everyday counterpart; pick libvips only when scale demands it
- ExifTool — libvips'
[strip]is all-or-nothing; for surgical metadata edits use exiftool - ffmpeg — for moving images / video frames
- Upstream API reference: https://www.libvips.org/API/current/
- Performance notes & benchmarks: https://github.com/libvips/libvips/wiki/Speed-and-memory-use