Examples
The snippets below show the main API shapes inline. For runnable
end-to-end scripts, see the examples in examples/:
-
examples/create_thumbnail.cljcreates a thumbnail from a local file and writes it back out. -
examples/chain_transforms.cljchains several image operations together with the threading style API. -
examples/compose_images.cljjoins two images and builds a small grid withjoinandarrayjoin. -
examples/bytes_and_streams.cljreads image bytes into memory, streams them through libvips, and writes the result back out. -
examples/http_stream_fetch.cljstreams an HTTP response body into libvips and saves a transformed result. -
examples/metadata_roundtrip.cljreads and writes metadata fields before saving an image. -
examples/animated_gif.cljloads every GIF frame, transforms each page, and writes an animated result.
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, andv/loop-count -
v/assoc-pages,v/assoc-page-height,v/assoc-page-delays, andv/assoc-loop-count -
v/extract-area-pages,v/embed-pages,v/rot-pages, andv/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))