vipsx

module
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: MIT

README

vipsx

Go Reference CI License

Go bindings for libvips, derived from the installed library at runtime.

English | 简体中文

Overview

libvips describes its own operations through the GObject type system. vipsx reads that description at runtime rather than wrapping operations individually, so a single call path covers every operation the installed libvips exposes, including operations added after this package was released.

Two APIs sit on that call path:

  • Typed API — one function and one options struct per operation, generated from the installed libvips. On 8.18 this is 330 functions and 47 enum types, entirely in Go: no generated C, and no per-operation cgo to compile.
  • Generic APICall, which accepts any operation name and resolves its signature at runtime. Used directly for operations the generator has not been run against.

Requirements

  • libvips 8.14 or later
  • Go 1.24 or later
  • cgo enabled, with a C toolchain

The libvips floor is set by continuous integration rather than by inspection: Debian 12 ships 8.14 and is supported until 2028.

Installation

brew install vips        # or: apt install libvips-dev
go get github.com/kirklin/vipsx

On macOS, cgo must be permitted to pass through the preprocessor flag libvips uses:

export CGO_CFLAGS_ALLOW=-Xpreprocessor

Documentation

API reference: pkg.go.dev/github.com/kirklin/vipsx

Usage

im, err := vips.LoadFile("photo.jpg")
if err != nil {
    return err
}
defer im.Close()

thumb, err := vips.ThumbnailImage(im, 640, &vips.ThumbnailImageOptions{
    Crop: vips.Ptr(vips.InterestingAttention),
})
if err != nil {
    return err
}
defer thumb.Close()

webp, err := vips.SaveBuffer(thumb, ".webp", vips.In("Q", 82))
Typed API
small, err := vips.Resize(im, 0.5, nil)
blur, err := vips.Gaussblur(small, 2.0, nil)
gray, err := vips.Colourspace(blur, vips.InterpretationBW, nil)
avg, err := vips.Avg(gray)

Optional arguments are pointer fields, so an argument that was not supplied is distinguishable from one explicitly set to zero. In libvips 8.18, 357 optional arguments have a non-zero default, where the two cases produce different results.

vips.Resize(im, 0.5, &vips.ResizeOptions{Kernel: vips.Ptr(vips.KernelNearest)})

Optional outputs are requested by pointing a field at a destination variable. Fields left nil are not requested, and their destinations are not written.

var x, y int
max, err := vips.Max(im, &vips.MaxOptions{X: &x, Y: &y})
Generic API

Argument names are libvips' own, as reported by vips <operation>.

outs, err := vips.Call("gaussblur", vips.In("in", im), vips.In("sigma", 3.0))
im, err := outs.Image("out")

Out requests an optional output. Describe, Operations and EnumValues report the signatures, operation list and enum members of the installed library.

Loading and saving

Input format is detected from content; output format is selected by extension.

im, err := vips.LoadFile("in.heic")
buf, err := vips.SaveBuffer(im, ".jpg", vips.In("Q", 90))

Sources and targets stream from an io.Reader and to an io.Writer without an intermediate file.

src, _ := vips.NewSourceFromReader(req.Body)
defer src.Close()
im, _ := vips.LoadSource(src)

target, _ := vips.NewTargetToWriter(w)
defer target.Close()
err = vips.SaveTarget(im, target, ".webp", vips.In("Q", 82))
if err := target.Err(); err != nil {
    // the error reported by the writer, rather than the generic libvips message
}

Semantics

Image sharing

libvips caches built operations, so two identical calls may return handles to the same underlying image. Concurrent reads are safe. Modifying an image header is not: the change is visible to every holder. Copy before modifying.

own, _ := vips.Copy(im, nil)
own.SetString("comment", "mine")

Operations that modify their input in place — the draw family — are handled by the binding. Call substitutes a private copy and returns it, so the argument supplied by the caller is never modified.

drawn, err := vips.DrawRect(im, []float64{255, 0, 0}, 60, 60, 300, 200, nil)
Handle lifetime

An image holds one libvips reference, released by Close or by the garbage collector. Use after Close panics with *ClosedError rather than dereferencing freed memory.

Handles are safe to use concurrently, Close included. Each method acquires its own reference before entering C, so a Close racing another call either follows a completed call or causes that call to panic with *ClosedError.

An image is a lazily evaluated pipeline rather than a buffer of pixels, so a streaming source must remain open until the image is evaluated. CopyMemory materialises the pixels and releases the dependency.

Cancellation

libvips has no deadline mechanism. CancelOn terminates the pipeline at its next progress report, and reports the cause.

w, _ := im.CancelOn(ctx)
defer w.Stop()

if _, err := vips.SaveBuffer(im, ".webp"); err != nil {
    if cause := w.Err(); cause != nil {
        return cause    // context.DeadlineExceeded, rather than a generic failure
    }
    return err
}

Security

For processes decoding untrusted input:

vips.BlockUntrusted(true)                          // block loaders libvips marks untrusted
vips.BlockOperation("VipsForeignLoad", true)       // or block all loaders,
vips.BlockOperation("VipsForeignLoadJpeg", false)  // then permit specific formats
vips.SetPipeReadLimit(64 << 20)                    // cap buffering of unseekable input

See SECURITY.md for the supported configuration and reporting process.

Testing

The binding contains no per-operation code, so correctness is established by differential testing rather than by review. internal/difftest executes each operation through this binding and through the vips command line, constructing both invocations from one set of argument values, and requires the results to match exactly. Both sides run pinned to a single worker thread, since several libvips reductions are not bit-reproducible across thread counts.

Target Scope
make test Unit tests
make race Unit tests under the race detector
make diff Differential comparison against the vips command line
make soak libvips allocation counters over 200 serial and 320 concurrent rounds
make cleak AddressSanitizer over the C core; reports whether leak detection was available
make cover Every operation exposed by govips and vipsgen must be reachable

Continuous integration runs the suite against libvips 8.14 (Debian 12 container), 8.15 (ubuntu-24.04) and 8.18 (macOS). A separate job regenerates the typed API against the installed library and requires the result to build and pass tests.

Compatibility

The typed API is generated from the installed libvips, so its surface varies with the version in use; the generic API does not. Releases follow semantic versioning, with the pre-1.0 caveat that minor versions may introduce breaking changes. vips.PackageVersion reports the release, vips.ModuleVersion the version resolved by the module graph, and vips.Version the libvips linked at runtime.

Comparison

Operation coverage is verified by internal/coverage, which requires every operation exposed by govips and vipsgen to be reachable here.

Binding Operations reached
vipsx 330
vipsgen 289
govips 185

vipsx differs from both in deriving its surface at runtime rather than shipping generated bindings per libvips version.

examples/gallery renders 35 operations against a photograph and writes an index page. The output is committed under site/, which carries a separate go.mod so that the images are excluded from the module archive.

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
vipsx-gen command
Command vipsx-gen writes the typed layer over the generic call path.
Command vipsx-gen writes the typed layer over the generic call path.
examples
gallery command
Command gallery runs a broad set of libvips operations through vipsx and writes the results next to an index page, so the output can be looked at rather than read about.
Command gallery runs a broad set of libvips operations through vipsx and writes the results next to an index page, so the output can be looked at rather than read about.
thumbnail command
Command thumbnail shows the whole of vipsx in one file: load an image, resize it, and write it out in another format.
Command thumbnail shows the whole of vipsx in one file: load an image, resize it, and write it out in another format.
internal
difftest
Package difftest checks this binding against the vips command line.
Package difftest checks this binding against the vips command line.
Package vips is a Go binding for libvips built on runtime introspection.
Package vips is a Go binding for libvips built on runtime introspection.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL