Examples

The snippets below show the main API shapes inline. For runnable end-to-end scripts, see the examples in examples/:

File Input And Output

Use the file helpers when your source and destination already live on disk and you want libvips to infer formats from the path or suffix.

(with-open [image (v/from-file "dev/rabbit.jpg" {:shrink 2})]
  (v/metadata image)
  (v/shape image)
  (v/write-to-file image "rabbit.png" {:compression 9})
  (v/write-to-buffer image ".png" {:compression 9}))

Metadata

ol.vips exposes a curated v/metadata summary and a generic header API for libvips metadata fields.

(with-open [image (v/from-file "dev/rabbit.jpg")]
  {:meta   (v/metadata image)
   :width  (v/field image "width")
   :fields (take 5 (v/field-names image))})
;; => {:meta {:width 2490, :height 3084, :bands 3, :has-alpha? false}
;;     :width 2490
;;     :fields ("width" "height" "bands" "format" "coding")}

Immutable metadata edits use assoc/update/dissoc style names.

(with-open [image  (v/from-file "dev/rabbit.jpg")
            tagged (-> image
                       (v/assoc-field "xres" 10.0)
                       (v/update-field "yres" (constantly 10.0)))]
  (v/write-to-file tagged "rabbit-copy.jpg" {:strip false})
  (select-keys (v/headers tagged) ["width" "height" "xres" "yres"]))

Animated Images

Load every page or frame with a format-specific loader and {:n -1}. libvips represents animated and multipage images as one tall strip plus metadata such as n-pages, page-height, loop, and delay.

(require '[ol.vips :as v]
         '[ol.vips.operations :as ops])

(with-open [image   (ops/gifload "test/fixtures/cogs.gif" {:n -1})
            cropped (v/extract-area-pages image 10 7 50 50)
            turned  (v/rot-pages cropped :d90)
            looped  (v/assoc-loop-count turned 2)]
  (v/write-to-file looped "cogs-turned.gif")
  (v/metadata looped))
;; => {:width 50, :height 250, :bands 4, :has-alpha? true, :pages 5, ...}

The dedicated animated helpers are:

  • v/pages, v/page-height, v/page-delays, and v/loop-count

  • v/assoc-pages, v/assoc-page-height, v/assoc-page-delays, and v/assoc-loop-count

  • v/extract-area-pages, v/embed-pages, v/rot-pages, and v/assemble-pages

These helpers work best for uniform-height multipage inputs such as animated GIF/WebP strips and similarly-shaped TIFF/PDF inputs.

For a deeper guide, see Multipage and Animated Images.

Image Loaders

The generic loaders v/from-file, v/from-buffer, and v/from-stream auto-detect the input format and accept option maps that libvips forwards to the selected loader. When you need format-specific behavior, use the generated loader operations in ol.vips.operations, such as ops/jpegload.

ol.vips blocks libvips operations marked as untrusted by default. This can block loaders with a larger attack surface, such as PDF or ImageMagick-backed formats.

If you trust your input and need those operations, opt in explicitly before loading that data:

(require '[ol.vips :as v]
         '[ol.vips.operations :as ops])

(v/set-block-untrusted-operations! false)

(with-open [image (ops/pdfload "document.pdf")]
  (v/metadata image))

Use that override only for trusted inputs. See the upstream vips_block_untrusted_set documentation. In libvips terms this is equivalent to calling vips_block_untrusted_set(FALSE) after initialization.

JPEG auto-rotation rotates the image according to its EXIF orientation at load time:

(require '[ol.vips :as v]
         '[ol.vips.operations :as ops])

(with-open [image (ops/jpegload "dev/rabbit.jpg" {:autorotate true})]
  (v/write-to-file image "rabbit-upright.jpg")
  (v/metadata image))

Streaming Input And Output

from-stream reads from any java.io.InputStream. from-buffer reads from a byte array already in memory.

(require '[babashka.http-client :as http]
         '[ol.vips :as v]
         '[ol.vips.operations :as ops])

(import '[java.io FileOutputStream])

(with-open [response-body (:body (http/get "https://casey.link/square-flask.png"
                                           {:as :stream}))
            image         (v/from-stream response-body {:access  :sequential
                                                        :fail-on :error})
            thumbnail     (ops/thumbnail-image image 200)
            out           (FileOutputStream. "square-flask-thumb.png")]
  (v/write-to-stream thumbnail out ".png")
  (v/metadata thumbnail))

write-to-stream writes encoded bytes to any java.io.OutputStream.

(require '[babashka.fs :as fs]
         '[ol.vips :as v]
         '[ol.vips.operations :as ops])

(import '[java.io FileOutputStream])

(let [source-bytes (fs/read-all-bytes "dev/rabbit.jpg")]
  (with-open [image     (v/from-buffer source-bytes)
              thumbnail (ops/thumbnail-image image 200)
              out       (FileOutputStream. "rabbit-thumb.png")]
    (v/write-to-stream thumbnail out ".png")
    (v/metadata thumbnail)))

Autorotate And Inspect Outputs

autorot returns a closeable result map. You can inspect :angle and :flip, and still use the same value anywhere an image is expected.

(with-open [image   (v/from-file "dev/rabbit.jpg")
            autorot (ops/autorot image)]
  {:angle (:angle autorot)
   :flip  (:flip autorot)
   :meta  (v/metadata autorot)})
;; => {:angle :d0, :flip false, :meta {:width 2490, :height 3084, :bands 3, :has-alpha? false}}

Resize And Crop

Use these geometry operations when you want to rescale an image first and then work on a precise rectangular region.

(with-open [image   (v/from-file "dev/rabbit.jpg")
            resized (ops/resize image 0.5)
            cropped (ops/extract-area resized 100 100 500 500)]
  (v/write-to-file resized "rabbit-resized.jpg")
  (v/write-to-file cropped "rabbit-cropped.jpg")
  {:resized (v/metadata resized)
   :cropped (v/metadata cropped)})

Smart Thumbnailing

ops/thumbnail exposes libvips’s higher-level thumbnail pipeline. Enum options such as :size and :crop are documented in ol.vips.enums.

(with-open [thumb (ops/thumbnail "dev/rabbit.jpg" 300
                                 {:height 300
                                  :size :down
                                  :crop :attention})]
  (v/write-to-file thumb "rabbit-smart-thumb.jpg")
  (v/metadata thumb))

Transforming Images

These operations are a good fit for orientation, color interpretation, and other structural changes you want to compose into one pipeline.

(with-open [image   (v/from-file "dev/rabbit.jpg")
            rotated (ops/rotate image 90.0)
            flipped (ops/flip rotated :horizontal)
            bw      (ops/colourspace flipped :b-w)]
  (v/write-to-file bw "rabbit-bw.jpg"))

Filters And Effects

libvips includes a large set of convolution and enhancement operations, so common blur and sharpen passes can stay inside the same image pipeline.

(with-open [image   (v/from-file "dev/rabbit.jpg")
            blurred (ops/gaussblur image 3.0)
            sharp   (ops/sharpen image {:sigma 1.0})]
  (v/write-to-file blurred "rabbit-blur.jpg")
  (v/write-to-file sharp "rabbit-sharp.jpg")
  {:blurred (v/metadata blurred)
   :sharp   (v/metadata sharp)})

Composing Images

Use the composition helpers when you need to join images, build contact sheets, or align multiple sources into one output image.

(with-open [left   (v/from-file "dev/rabbit.jpg")
            right  (v/from-file "dev/rabbit.jpg")
            joined (ops/join left right :horizontal)
            grid   (ops/arrayjoin [left right left right]
                                  {:across 2
                                   :shim   10
                                   :halign :centre
                                   :valign :centre})]
  (v/write-to-file joined "rabbit-joined.jpg")
  (v/write-to-file grid "rabbit-grid.jpg"))

Web Optimization

The save helpers accept format-specific encoder options, which makes it easy to produce smaller web-friendly JPEG and WebP outputs from the same source image.

(with-open [image (v/from-file "dev/rabbit.jpg")]
  (v/write-to-file image "rabbit-progressive.jpg"
                   {:interlace true
                    :strip true
                    :Q 85})
  (v/write-to-file image "rabbit.webp"
                   {:Q 80
                    :effort 4}))

Calling Raw Operations

Use v/call when you want access to the full libvips operation surface before a dedicated convenience wrapper exists.

(with-open [image   (v/from-file "dev/rabbit.jpg")
            rotated (v/call "rotate" {:in image :angle 90.0})]
  (v/metadata rotated))

Use v/operations to list available libvips operations and v/operation-info to inspect their inputs and outputs.

Text Overlay

Generated operation wrappers also cover image synthesis and compositing, so overlays like text labels can stay inside libvips rather than being rendered in a separate tool.

(with-open [image  (v/from-file "dev/rabbit.jpg")
            label  (ops/text "ol.vips"
                             {:font "Sans Bold 48"
                              :rgba true})
            poster (ops/composite2 image label :over {:x 40 :y 40})]
  (v/write-to-file poster "rabbit-poster.png")
  (v/metadata poster))