Editing images using code
Painting with a hammer, blindfolded
2018-10-16 — 2026-04-19
Wherein several image-processing tools are surveyed, the rivalry between ImageMagick and GraphicsMagick is remarked upon, and vips’s demand-driven pipeline approach is described.
The command line is not the right tool for images. Even I have to admit that. OTOH the command line is a better tool for automating things than a GUI, sometimes even for images.
For ML-based editing — instruction-following edit models, background removal, upscaling, face restoration — see editing images with machine learning.
1 vips
vips is my current go-to. I think it’s under-rated.
libvips is a demand-driven, horizontally threaded image processing library. Compared to similar libraries, libvips runs quickly and uses little memory. libvips is licensed under the LGPL 2.1+.
It has around 300 operations covering arithmetic, histograms, convolution, morphological operations, frequency filtering, colour, resampling, statistics and others. It supports a large range of numeric formats, from 8-bit int to 128-bit complex. Images can have any number of bands. It supports a good range of image formats, including JPEG, TIFF, PNG, WebP, FITS, Matlab, OpenEXR, PDF, SVG, HDR, PPM, CSV, GIF, Analyze, NIfTI, DeepZoom, and OpenSlide. It can also load images via ImageMagick or GraphicsMagick, letting it load formats like DICOM.
It comes with bindings for C, C++, and the command-line. Full bindings are available for Ruby, Python, PHP, .NET, Go, and Lua. libvips is used as an image processing engine by sharp (on node.js), bimg, sharp for Go, Ruby on Rails, carrierwave-vips, mediawiki, PhotoFlow and others. The official libvips GUI is nip2, a strange combination of a spreadsheet and a photo editor.
It seems to optimally pipeline operations and stream them from disk, which is much better for typical use cases. Documentation for vips is not amazing, but it is bloody good software. There is a CLI interface, which is under-advertised but very useful. Occasionally I need to deduce what it does from the API documentation rather than a nice man page, but usually I’ve guessed right so far.
Also notable: vips supported the fancy new AVIF format before its competitors, who were still arguing about it long after every browser supported it. That is why vips is part of the build-chain of this very site, generating AVIF thumbnails.
2 graphicsmagic/imagemagick
graphicsmagick and imagemagick are similar but hate each other like competitive siblings. Imagemagick is the “original”, whatever that might mean in the tangled phylogeny of software intellectual property. graphicsmagick is the younger sibling who claims that its more famous and successful elder sold out. FWIW Graphicsmagick seems to have a better API, but most users probably don’t care. They are reasonably interchangeable from this user’s perspective. I think imagemagics command names are grandiose and graphicsmagick’s are more sensible, FWIW. From a developer perspective, IM pretends GM doesn’t exist, whereas GM knows IM exists and thinks it’s awful:
Here are some reasons to prefer GraphicsMagick over ImageMagick or other popular software:
- GM is more efficient than ImageMagick so it gets the job done faster using fewer resources.
- GM is much smaller and lighter than ImageMagick (3-5X smaller installation footprint).
- GM is used to process billions of files at the world’s largest photo sites (e.g. Flickr and Etsy).
- GM does not conflict with other installed software.
- GM suffers from fewer security issues and exploits than ImageMagick.
- …
2.1 imagemagick hacks
Fred Weinhaus’s ImageMagick scripts show how to do a great many useful things, e.g. Histogram matching.
Beware the idiosyncratic licensing.
2.2 favicon
3 OpenCV
Old, but it still works. OpenCV is the classical computer-vision library — image I/O, transformations, filters, contours, optical flow, all the standard CV operations. Bindings for many languages; the Python bindings are the easy way in. Not a replacement for vips for raw image-processing throughput, but indispensable when we want a specific classical algorithm rather than a generic operation.
4 G’MIC
G’MIC includes a world of image conversion including scriptable image processing pipelines. See, e.g., a hand-rolled fingerpainting filter via diffusion tensor fields. Also has GIMP and Krita plug-in versions.
G'MICis a full-featured open-source framework for digital image processing… It provides several user interfaces to convert / manipulate / filter / visualize generic image datasets, ranging from 1D scalar signals to 3D+t sequences of multi-spectral volumetric images, hence including 2D colour images.
Doing animated GIFs? They’re fiddly. Specialised tool gifsicle handles them.
5 Scripting GIMP
GIMP supports automation and scripting through several built-in interfaces, covering both interactive GUI workflows and headless CLI batch processing.
5.1 Scripting Languages
GIMP exposes its internals via the Procedural Database (PDB), which can be called from multiple languages:
- Script-Fu — a Scheme/Lisp dialect built into GIMP via a TinyScheme interpreter; the default scripting language
- Python-Fu — Python bindings to the same PDB, using standard Python syntax
- Perl and Tcl — available via external interpreters
- C plug-ins — compiled native extensions for performance-critical operations
5.2 Interactive GUI Consoles
Under the Filters menu, GIMP provides interactive REPL consoles for live scripting against an open image:
- Filters → Script-Fu → Console — runs Scheme expressions against the current image
- Filters → Python-Fu → Console — same, but for Python
Scripts placed in GIMP’s scripts directory (e.g. ~/.config/GIMP/2.10/scripts/) are automatically registered as menu entries under Filters, optionally exposing a parameter dialog.
5.3 CLI and Headless Batch Mode
GIMP can run without a display using the gimp CLI flags:
-i— disables the GUI-b '<expression>'— evaluates a Script-Fu or Python-Fu expression; can be chained-b '(gimp-quit 0)'— exits cleanly after batch operations complete
A typical invocation:
This makes GIMP scriptable from a shell, Makefile, or subprocess call. See the Stack Overflow reference for worked examples of CLI Script-Fu invocation.
5.4 Batch GUI Plugin
BIMP (Batch Image Manipulation Plugin) provides a GUI-driven batch queue without requiring hand-written scripts, supporting operations like resize, crop, colour adjustments, and filter application across many files at once. I have tried to make this do useful things for me but without success; I just cannot work out how to set the parameters adaptively.
6 sips (macOS built-in)
If you’re on macOS and need something quick without installing anything, sips (Scriptable Image Processing System) is already on your machine. It handles resizing, format conversion, rotation, flipping, and metadata queries. It’s not as powerful as the tools above, but the zero-install friction is hard to beat for one-off tasks.
It can also execute JavaScript for more complex image manipulation via its -j flag, and its functionality is available via AppleScript’s “Image Events” suite. The JS scripting side is poorly documented by Apple; sips-js-api reverse-engineers the JavaScript API into proper documentation, which makes the scripting mode actually usable.
