Install
openclaw skills install libvips-imageHigh-performance image processing with libvips. Use for resizing, converting, watermarking, thumbnails, and batch image operations with low memory usage.
openclaw skills install libvips-imageFast, memory-efficient image processing using libvips via pyvips. Supports 300+ operations including resize, crop, rotate, convert, watermark, composite, and more. Ideal for batch processing large images.
# Recommended: Auto-detect OS and install everything
./scripts/install.sh
The install script will:
macOS (Homebrew):
brew install vips
uv pip install pyvips # preferred
# or: pip install pyvips
Ubuntu/Debian:
sudo apt-get install libvips-dev
uv pip install pyvips # preferred
# or: pip install pyvips
Fedora/RHEL:
sudo dnf install vips-devel
uv pip install pyvips
Arch Linux:
sudo pacman -S libvips
uv pip install pyvips
Windows (PowerShell, recommended):
# One-click install (downloads libvips + installs pyvips)
.\scripts\install.ps1
Windows (Manual):
# Option 1: winget (if available)
winget install libvips.libvips
# Option 2: scoop
scoop install libvips
# Option 3: Manual download
# Download from https://github.com/libvips/libvips/releases
# Extract to C:\vips or %LOCALAPPDATA%\vips
# Add bin\ to PATH
# Install pyvips
uv pip install pyvips
# or: pip install pyvips
Install uv (if not installed):
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
irm https://astral.sh/uv/install.ps1 | iex
macOS/Linux - Using run.sh wrapper (recommended):
./scripts/run.sh vips_tool.py resize input.jpg output.jpg --width 800
./scripts/run.sh vips_tool.py convert input.jpg output.webp --quality 85
./scripts/run.sh vips_tool.py thumbnail input.jpg thumb.jpg --size 200
./scripts/run.sh vips_batch.py resize ./input ./output --width 800
Windows - Using run.bat wrapper (recommended):
.\scripts\run.bat vips_tool.py resize input.jpg output.jpg --width 800
.\scripts\run.bat vips_tool.py convert input.jpg output.webp --quality 85
.\scripts\run.bat vips_tool.py thumbnail input.jpg thumb.jpg --size 200
.\scripts\run.bat vips_batch.py resize .\input .\output --width 800
Cross-platform - Using uv (after uv sync):
uv run python scripts/vips_tool.py resize input.jpg output.jpg --width 800
Direct Python (if library paths are configured):
python scripts/vips_tool.py resize input.jpg output.jpg --width 800
python scripts/vips_tool.py convert input.jpg output.webp --quality 85
python scripts/vips_tool.py thumbnail input.jpg thumb.jpg --size 200
python scripts/vips_tool.py watermark input.jpg output.jpg --text "Copyright 2024"
| Format | Read | Write | Notes |
|---|---|---|---|
| JPEG | Yes | Yes | Quality 1-100 |
| PNG | Yes | Yes | Compression 0-9 |
| WebP | Yes | Yes | Lossy/lossless |
| AVIF | Yes | Yes | Modern, high compression |
| HEIC | Yes | Yes | Apple format |
| TIFF | Yes | Yes | Multi-page support |
| GIF | Yes | Yes | Animated support |
| Yes | Yes | Via poppler | |
| SVG | Yes | No | Via librsvg |
| RAW | Yes | No | Via libraw |
Resize images with various fit modes.
# Resize to exact width, maintain aspect ratio
python scripts/vips_tool.py resize input.jpg output.jpg --width 800
# Resize to exact height
python scripts/vips_tool.py resize input.jpg output.jpg --height 600
# Resize to fit within bounds
python scripts/vips_tool.py resize input.jpg output.jpg --width 800 --height 600
# Resize to cover (fill) dimensions
python scripts/vips_tool.py resize input.jpg output.jpg --width 800 --height 600 --mode cover
# Force exact dimensions (may distort)
python scripts/vips_tool.py resize input.jpg output.jpg --width 800 --height 600 --mode force
Resize modes:
fit (default): Fit within bounds, maintain aspect ratiocover: Cover bounds, crop excessforce: Force exact dimensionsCreate optimized thumbnails with smart cropping.
# Square thumbnail
python scripts/vips_tool.py thumbnail input.jpg thumb.jpg --size 200
# Attention-based smart crop
python scripts/vips_tool.py thumbnail input.jpg thumb.jpg --size 200 --crop attention
# Center crop
python scripts/vips_tool.py thumbnail input.jpg thumb.jpg --size 200 --crop centre
Crop strategies:
none: No cropping, fit within sizecentre: Crop from centerattention: Smart crop focusing on interesting areasentropy: Crop to maximize entropyConvert between image formats with quality control.
# JPEG to WebP
python scripts/vips_tool.py convert input.jpg output.webp --quality 85
# PNG to AVIF (modern format, great compression)
python scripts/vips_tool.py convert input.png output.avif --quality 50
# JPEG to PNG (lossless)
python scripts/vips_tool.py convert input.jpg output.png
# With compression level for PNG
python scripts/vips_tool.py convert input.jpg output.png --compression 9
Extract a region from an image.
# Crop 400x300 region starting at (100, 50)
python scripts/vips_tool.py crop input.jpg output.jpg --left 100 --top 50 --width 400 --height 300
# Smart crop to aspect ratio
python scripts/vips_tool.py crop input.jpg output.jpg --width 800 --height 600 --smart
Rotate images by any angle.
# Rotate 90 degrees clockwise
python scripts/vips_tool.py rotate input.jpg output.jpg --angle 90
# Rotate 45 degrees with background color
python scripts/vips_tool.py rotate input.jpg output.jpg --angle 45 --background "255,255,255"
# Auto-rotate based on EXIF
python scripts/vips_tool.py rotate input.jpg output.jpg --auto
Add text or image watermarks.
# Text watermark
python scripts/vips_tool.py watermark input.jpg output.jpg --text "Copyright 2024"
# Position: top-left, top-right, bottom-left, bottom-right, center
python scripts/vips_tool.py watermark input.jpg output.jpg --text "Logo" --position bottom-right
# With opacity
python scripts/vips_tool.py watermark input.jpg output.jpg --text "Draft" --opacity 0.3
# Image watermark
python scripts/vips_tool.py watermark input.jpg output.jpg --image logo.png --position bottom-right --opacity 0.5
Combine multiple images.
# Overlay image on background
python scripts/vips_tool.py composite background.jpg overlay.png output.jpg
# With position offset
python scripts/vips_tool.py composite background.jpg overlay.png output.jpg --x 100 --y 50
# With blend mode
python scripts/vips_tool.py composite background.jpg overlay.png output.jpg --blend multiply
Blend modes: over, multiply, screen, overlay, darken, lighten
Adjust brightness, contrast, saturation.
# Increase brightness
python scripts/vips_tool.py adjust input.jpg output.jpg --brightness 1.2
# Increase contrast
python scripts/vips_tool.py adjust input.jpg output.jpg --contrast 1.3
# Increase saturation
python scripts/vips_tool.py adjust input.jpg output.jpg --saturation 1.5
# Combine adjustments
python scripts/vips_tool.py adjust input.jpg output.jpg --brightness 1.1 --contrast 1.2 --saturation 1.1
Apply sharpening filter.
# Default sharpen
python scripts/vips_tool.py sharpen input.jpg output.jpg
# Custom sigma (blur radius)
python scripts/vips_tool.py sharpen input.jpg output.jpg --sigma 1.5
# Custom parameters
python scripts/vips_tool.py sharpen input.jpg output.jpg --sigma 1.5 --x1 2 --m2 3
Apply Gaussian blur.
# Default blur
python scripts/vips_tool.py blur input.jpg output.jpg
# Custom sigma
python scripts/vips_tool.py blur input.jpg output.jpg --sigma 5
Flip images horizontally or vertically.
# Horizontal flip (mirror)
python scripts/vips_tool.py flip input.jpg output.jpg --horizontal
# Vertical flip
python scripts/vips_tool.py flip input.jpg output.jpg --vertical
Convert to grayscale.
python scripts/vips_tool.py grayscale input.jpg output.jpg
Get image metadata.
python scripts/vips_tool.py info input.jpg
Output:
File: input.jpg
Format: jpeg
Width: 3840
Height: 2160
Bands: 3
Interpretation: srgb
Size: 2.4 MB
Process multiple images at once.
# Resize all JPEGs in a directory
python scripts/vips_batch.py resize ./input ./output --width 800 --pattern "*.jpg"
# Convert all images to WebP
python scripts/vips_batch.py convert ./input ./output --format webp --quality 85
# Create thumbnails for all images
python scripts/vips_batch.py thumbnail ./input ./thumbnails --size 200
# Custom batch with JSON config
python scripts/vips_batch.py --config batch_config.json
{
"input_dir": "./input",
"output_dir": "./output",
"operations": [
{"type": "resize", "width": 1920},
{"type": "sharpen", "sigma": 0.5},
{"type": "convert", "format": "webp", "quality": 85}
],
"pattern": "*.{jpg,jpeg,png}",
"recursive": true,
"workers": 4
}
import pyvips
# Load image
image = pyvips.Image.new_from_file("input.jpg")
# Resize
resized = image.resize(0.5) # 50% scale
resized = image.thumbnail_image(800) # 800px width
# Save
resized.write_to_file("output.jpg", Q=85) # JPEG quality 85
resized.write_to_file("output.webp", Q=85) # WebP quality 85
import pyvips
# Load, process, save in one pipeline
image = pyvips.Image.new_from_file("input.jpg", access="sequential")
result = (
image
.thumbnail_image(1200)
.sharpen(sigma=0.5)
.write_to_file("output.webp", Q=85)
)
import pyvips
image = pyvips.Image.new_from_file("input.jpg")
# Create text overlay
text = pyvips.Image.text(
"Copyright 2024",
font="sans 24",
rgba=True
)
# Composite at bottom-right
x = image.width - text.width - 20
y = image.height - text.height - 20
result = image.composite2(text, "over", x=x, y=y)
result.write_to_file("output.jpg")
import pyvips
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
def process_image(input_path, output_dir, width=800):
image = pyvips.Image.new_from_file(str(input_path), access="sequential")
thumbnail = image.thumbnail_image(width)
output_path = output_dir / f"{input_path.stem}.webp"
thumbnail.write_to_file(str(output_path), Q=85)
return output_path
input_dir = Path("./input")
output_dir = Path("./output")
output_dir.mkdir(exist_ok=True)
files = list(input_dir.glob("*.jpg"))
with ThreadPoolExecutor(max_workers=4) as executor:
results = executor.map(lambda f: process_image(f, output_dir), files)
| Parameter | Description | Default |
|---|---|---|
--width | Target width in pixels | - |
--height | Target height in pixels | - |
--size | Thumbnail size (square) | 200 |
--quality | Output quality (1-100) | 85 |
--compression | PNG compression (0-9) | 6 |
--mode | Resize mode: fit, cover, force | fit |
--crop | Crop strategy | none |
--angle | Rotation angle in degrees | 0 |
--sigma | Blur/sharpen radius | 1.0 |
--opacity | Watermark opacity (0-1) | 0.5 |
--position | Watermark position | bottom-right |
--workers | Batch processing threads | 4 |
--pattern | File glob pattern | . |
--recursive | Process subdirectories | false |
| Tip | Description |
|---|---|
| Sequential access | Use access="sequential" for streaming |
| Pipeline operations | Chain operations before writing |
| Parallel processing | Use ThreadPoolExecutor for batches |
| Format selection | WebP/AVIF for web, JPEG for photos |
| Quality settings | 85 for quality, 75 for size |
| Thumbnail vs resize | thumbnail_image is faster for downscaling |
libvips uses a streaming architecture:
| Issue | Solution |
|---|---|
| "Cannot find libvips" | Install via brew/apt, check PATH |
| Slow processing | Use sequential access, check disk I/O |
| Memory errors | Increase cache, reduce workers |
| Format not supported | Install optional dependencies |
| Poor quality | Increase quality parameter |
| HEIC not working | Install libheif: brew install libheif |
| SVG not rendering | Install librsvg: brew install librsvg |
| Issue | Solution |
|---|---|
| "cannot load library 'libvips-42.dll'" | Add vips bin\ folder to PATH |
| DLL not found after install | Restart terminal/PowerShell |
| winget install fails | Use manual download or scoop |
| Permission denied | Run PowerShell as Administrator |
| PATH not updated | Log out and log back in, or restart |
Windows PATH Setup (Manual):
# Add to current session
$env:PATH = "C:\vips\bin;$env:PATH"
# Add permanently (run as Admin or for current user)
[Environment]::SetEnvironmentVariable("PATH", "C:\vips\bin;$env:PATH", "User")
| Issue | Solution |
|---|---|
| "cannot load library 'libvips.42.dylib'" | Use ./scripts/run.sh wrapper |
| DYLD_LIBRARY_PATH not working | macOS SIP blocks env vars; use run.sh |
| Homebrew Python issues | Use /opt/homebrew/bin/python3 directly |
macOS Library Path Setup:
# Add to ~/.zshrc or ~/.bashrc
export DYLD_LIBRARY_PATH="/opt/homebrew/lib:$DYLD_LIBRARY_PATH"
| Issue | Solution |
|---|---|
| Package not found | Check distro-specific package name |
| ldconfig issues | Run sudo ldconfig after install |
| Permission denied | Use sudo for system packages |