# Examples

The snippets below show the main API shapes inline. For runnable
end-to-end scripts, see the examples in [`examples/`](https://github.com/outskirtslabs/vips/tree/main/examples):

* [`examples/create_thumbnail.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/create_thumbnail.clj) creates a thumbnail from a local file and writes it back out.
* [`examples/chain_transforms.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/chain_transforms.clj) chains several image operations together with the threading style API.
* [`examples/compose_images.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/compose_images.clj) joins two images and builds a small grid with `join` and `arrayjoin`.
* [`examples/bytes_and_streams.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/bytes_and_streams.clj) reads image bytes into memory, streams them through libvips, and writes the result back out.
* [`examples/http_stream_fetch.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/http_stream_fetch.clj) streams an HTTP response body into libvips and saves a transformed result.
* [`examples/metadata_roundtrip.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/metadata_roundtrip.clj) reads and writes metadata fields before saving an image.
* [`examples/animated_gif.clj`](https://github.com/outskirtslabs/vips/blob/main/examples/animated_gif.clj) loads 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.

```clojure
(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.

```clojure
(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.

```clojure
(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`.

```clojure
(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](https://docs.outskirtslabs.com/ol.vips/next/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:

```clojure
(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
https://www.libvips.org/API/8.17/func.block_untrusted_set.html[`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:

```clojure
(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.

```clojure
(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`.

```clojure
(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.

```clojure
(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.

```clojure
(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`.

```clojure
(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.

```clojure
(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.

```clojure
(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.

```clojure
(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.

```clojure
(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.

```clojure
(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.

```clojure
(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))
```
