Liking cljdoc? Tell your friends :D

com.blockether.imaging

Clojure imaging WITHOUT java.desktop — decoding, encoding, transforms, vector drawing, text, SVG rasterisation and plotting, all in-process through the JDK Foreign Function & Memory API over a first-party Rust cdylib (native/imaging-c: the image crate + resvg/usvg/tiny-skia).

Why it exists: javax.imageio, java.awt.image.BufferedImage and Graphics2D drag the whole AWT/Java2D/ImageIO subgraph — service loaders, sun.java2d.loops JNI blit primitives, the font manager — into a GraalVM native image, which is both huge and, on a headless server, pointless. This library replaces that surface with a ~5 MB cdylib and zero JNI: pure downcalls, no subprocess, no -Djava.awt.headless, no fontconfig.

Everything is bytes in, bytes out. An Img is an opaque handle on the Rust side; it is AutoCloseable (use with-open for tight loops) AND registered with a java.lang.ref.Cleaner, so forgetting to close leaks nothing permanently.

Run the JVM with --enable-native-access=ALL-UNNAMED so the foreign linker may load the library without a restricted-method warning.

The library is resolved ONCE, lazily, the first time it's needed:

  1. IMAGING_NATIVE_PATH env / com.blockether.imaging.native.path system property — an explicit path to the cdylib (used verbatim).
  2. A bundled classpath resource prebuilds/<platform>/<lib>, shipped by com.blockether/imaging-native-<platform>. This is the native-image path.
  3. A runtime download: the imaging-native-<platform> jar resolved through clojure.tools.deps (honouring Maven repos/mirrors/settings.xml), extracted + cached. Disable with IMAGING_DISABLE_DOWNLOAD=1.

<platform> in { linux-x64 linux-arm64 darwin-arm64 darwin-x64 windows-x64 }.

Clojure imaging WITHOUT `java.desktop` — decoding, encoding, transforms,
vector drawing, text, SVG rasterisation and plotting, all in-process through
the JDK Foreign Function & Memory API over a first-party Rust cdylib
(`native/imaging-c`: the `image` crate + `resvg`/`usvg`/`tiny-skia`).

Why it exists: `javax.imageio`, `java.awt.image.BufferedImage` and
`Graphics2D` drag the whole AWT/Java2D/ImageIO subgraph — service loaders,
`sun.java2d.loops` JNI blit primitives, the font manager — into a GraalVM
native image, which is both huge and, on a headless server, pointless. This
library replaces that surface with a ~5 MB cdylib and zero JNI: pure
downcalls, no subprocess, no `-Djava.awt.headless`, no fontconfig.

Everything is bytes in, bytes out. An `Img` is an opaque handle on the Rust
side; it is `AutoCloseable` (use `with-open` for tight loops) AND registered
with a `java.lang.ref.Cleaner`, so forgetting to close leaks nothing
permanently.

Run the JVM with `--enable-native-access=ALL-UNNAMED` so the foreign linker
may load the library without a restricted-method warning.

The library is resolved ONCE, lazily, the first time it's needed:
  1. IMAGING_NATIVE_PATH env / `com.blockether.imaging.native.path` system
     property — an explicit path to the cdylib (used verbatim).
  2. A bundled classpath resource `prebuilds/<platform>/<lib>`, shipped by
     `com.blockether/imaging-native-<platform>`. This is the native-image path.
  3. A runtime download: the `imaging-native-<platform>` jar resolved through
     `clojure.tools.deps` (honouring Maven repos/mirrors/settings.xml),
     extracted + cached. Disable with IMAGING_DISABLE_DOWNLOAD=1.

`<platform>` in { linux-x64 linux-arm64 darwin-arm64 darwin-x64 windows-x64 }.
raw docstring

adjustclj

(adjust img opts)

Photometric adjustment: :brightness :contrast :saturation :opacity (1.0 = unchanged).

Photometric adjustment: `:brightness` `:contrast` `:saturation` `:opacity`
(1.0 = unchanged).
sourceraw docstring

blankclj

(blank w h)
(blank w h c)

A new w x h image filled with c (default transparent).

A new `w` x `h` image filled with `c` (default transparent).
sourceraw docstring

blurclj

(blur img sigma)
source

close!clj

(close! img)

Free an image handle now. Idempotent; Img is also AutoCloseable.

Free an image handle now. Idempotent; `Img` is also `AutoCloseable`.
sourceraw docstring

colorclj

(color c)

A colour as the packed 0xRRGGBBAA long the cdylib takes. Accepts a packed integer, "#rgb" / "#rrggbb" / "#rrggbbaa", a basic CSS colour name (string or keyword), or [r g b] / [r g b a] with 0-255 channels (alpha may also be a 0.0-1.0 double).

A colour as the packed `0xRRGGBBAA` long the cdylib takes. Accepts a packed
integer, `"#rgb"` / `"#rrggbb"` / `"#rrggbbaa"`, a basic CSS colour name
(string or keyword), or `[r g b]` / `[r g b a]` with 0-255 channels (alpha may
also be a 0.0-1.0 double).
sourceraw docstring

convertclj

(convert data)
(convert data opts)

One-shot decode -> normalise -> re-encode: the "make this attachment safe to send" path, without ever materialising an image handle.

Options: :format :quality :max-width :max-height :width :height :background (flatten alpha onto it) :filter :max-bytes (retry at lower quality/scale until the output fits). Returns a byte[].

One-shot decode -> normalise -> re-encode: the "make this attachment safe to
send" path, without ever materialising an image handle.

Options: `:format` `:quality` `:max-width` `:max-height` `:width` `:height`
`:background` (flatten alpha onto it) `:filter` `:max-bytes` (retry at lower
quality/scale until the output fits). Returns a byte[].
sourceraw docstring

convolveclj

(convolve img size kernel)
(convolve img size kernel {:keys [scale offset] :or {scale 0 offset 0}})

Correlate img with an odd size x size kernel (a seq of size*size weights, row-major) — blur, sharpen, emboss, edge detect: Pillow's ImageFilter.Kernel, and the same arithmetic.

:scale divides the weighted sum (0 or nil = no division) and :offset is added afterwards; the result is rounded half-up and clamped to 0..255. Edge samples clamp to the border pixel and the source ALPHA is carried through untouched, so blurring never eats a mask.

Correlate `img` with an odd `size` x `size` `kernel` (a seq of `size*size`
weights, row-major) — blur, sharpen, emboss, edge detect: Pillow's
`ImageFilter.Kernel`, and the same arithmetic.

`:scale` divides the weighted sum (0 or nil = no division) and `:offset` is
added afterwards; the result is rounded half-up and clamped to 0..255. Edge
samples clamp to the border pixel and the source ALPHA is carried through
untouched, so blurring never eats a mask.
sourceraw docstring

cropclj

(crop img x y w h)
source

decodeclj

(decode data)

Decode PNG/JPEG/WebP/GIF/BMP/TIFF/ICO/QOI/PNM/TGA/HDR/EXR bytes — or an SVG/SVGZ document, sized the way a browser would (see svg-canvas) — into an Img handle. Close it (with-open) when done.

Decode PNG/JPEG/WebP/GIF/BMP/TIFF/ICO/QOI/PNM/TGA/HDR/EXR bytes — or an
SVG/SVGZ document, sized the way a browser would (see `svg-canvas`) — into an
`Img` handle. Close it (`with-open`) when done.
sourceraw docstring

decode-gifclj

(decode-gif data)

Decode an animated (or still) GIF into {:width :height :loop-count :frames}, where each frame is {:delay-ms :rgba} with :rgba the straight RGBA8 rows as a byte[] (width*height*4). :loop-count is the iteration count, -1 for loop forever. The native multi-frame path — an animated GIF no longer needs a hand-rolled Clojure codec.

Decode an animated (or still) GIF into `{:width :height :loop-count :frames}`,
where each frame is `{:delay-ms :rgba}` with `:rgba` the straight RGBA8 rows
as a byte[] (`width*height*4`). `:loop-count` is the iteration count, -1 for
loop forever. The native multi-frame path — an animated GIF no longer needs a
hand-rolled Clojure codec.
sourceraw docstring

decode-videoclj

(decode-video data)
(decode-video data opts)

Decode an MP4's H.264 track into {:format :codec :encoding :width :height :source-width :source-height :frame-count :total-frames :duration-s :fps :frames}, where each frame is {:index :timestamp-s :data} and :data is a byte[].

:encoding decides what those bytes are: "rgba" (default) is straight RGBA8 rows, width*height*4, ready for from-pixels; anything encode understands ("png", "jpeg", "webp", ...) is an ENCODED still, which is far smaller and what a terminal or browser wants anyway.

Frames come out in DISPLAY order (B-frames are reordered), and RGBA is converted with the BT.601 limited-range matrix.

Options bound the work — the whole clip is decoded into memory otherwise: :max-frames (stop after N), :stride (keep every Nth frame), :max-dimension (downscale to fit), :filter, plus :quality for lossy :encoding.

Decode an MP4's H.264 track into
`{:format :codec :encoding :width :height :source-width :source-height
:frame-count :total-frames :duration-s :fps :frames}`, where each frame is
`{:index :timestamp-s :data}` and `:data` is a byte[].

`:encoding` decides what those bytes are: `"rgba"` (default) is straight
RGBA8 rows, `width*height*4`, ready for `from-pixels`; anything `encode`
understands (`"png"`, `"jpeg"`, `"webp"`, ...) is an ENCODED still, which is
far smaller and what a terminal or browser wants anyway.

Frames come out in DISPLAY order (B-frames are reordered), and RGBA is
converted with the BT.601 limited-range matrix.

Options bound the work — the whole clip is decoded into memory otherwise:
`:max-frames` (stop after N), `:stride` (keep every Nth frame),
`:max-dimension` (downscale to fit), `:filter`, plus `:quality` for lossy
`:encoding`.
sourceraw docstring

docxclj

(docx spec)

A .docx document as bytes (hand-written WordprocessingML).

{:properties {…} :page {:width-pt 595 :height-pt 842 :landscape false :margin-pt 72} :blocks [{:type :heading :level 1 :text "Q3"} {:type :paragraph :style :Quote :align :center :bullet true :runs [{:text "revenue "} {:text "up" :bold true :color "#c00"}]} {:type :table :header true :borders true :rows [{:cells [{:text "a"} {:runs [{:text "b" :bold true}]}]}]} {:type :image :data <bytes> :width-pt 240 :alt "chart"} {:type :page-break}]}

:body is accepted as a synonym for :blocks. Font sizes are points, spacing/indent *-pt keys are points; the module converts to half-points and twips.

A `.docx` document as bytes (hand-written WordprocessingML).

`{:properties {…}
  :page {:width-pt 595 :height-pt 842 :landscape false :margin-pt 72}
  :blocks [{:type :heading :level 1 :text "Q3"}
           {:type :paragraph :style :Quote :align :center :bullet true
            :runs [{:text "revenue "} {:text "up" :bold true :color "#c00"}]}
           {:type :table :header true :borders true
            :rows [{:cells [{:text "a"} {:runs [{:text "b" :bold true}]}]}]}
           {:type :image :data <bytes> :width-pt 240 :alt "chart"}
           {:type :page-break}]}`

`:body` is accepted as a synonym for `:blocks`. Font sizes are points,
spacing/indent `*-pt` keys are points; the module converts to half-points and
twips.
sourceraw docstring

draw!clj

(draw! img ops)

Run a batch of vector drawing ops on img, IN PLACE — this is the Graphics2D replacement. One call per batch keeps FFI chatter out of drawing loops; ops are applied in order and inherit the batch's style defaults.

Style keys (batch level or per op): :fill :stroke :stroke-width :dash :cap (:butt :round :square) :join (:miter :round :bevel) :size :family :weight :italic :letter-spacing :line-height.

Ops (:op): :clear — fill everything with :fill :clip — clip to :x :y :w :h (:op :reset-clip to drop it) :line:x1 :y1 :x2 :y2 (or :points) :polyline / :polygon:points [[x y] ...], :close :rect:x :y :w :h, optional :radius (rounded) :circle:cx :cy :r :ellipse:cx :cy :rx :ry :arc / :wedge:cx :cy :r :r-inner :start :end (degrees) :path:d (SVG path data), :fill-rule :text:text :x :y :anchor (:start|:middle|:end) :baseline :rotate :image:image (an Img), :x :y :w :h :opacity

Returns img.

Run a batch of vector drawing ops on `img`, IN PLACE — this is the
`Graphics2D` replacement. One call per batch keeps FFI chatter out of drawing
loops; ops are applied in order and inherit the batch's style defaults.

Style keys (batch level or per op): `:fill` `:stroke` `:stroke-width` `:dash`
`:cap` (`:butt` `:round` `:square`) `:join` (`:miter` `:round` `:bevel`)
`:size` `:family` `:weight` `:italic` `:letter-spacing` `:line-height`.

Ops (`:op`):
  `:clear`     — fill everything with `:fill`
  `:clip`      — clip to `:x :y :w :h` (`:op :reset-clip` to drop it)
  `:line`      — `:x1 :y1 :x2 :y2` (or `:points`)
  `:polyline` / `:polygon` — `:points [[x y] ...]`, `:close`
  `:rect`      — `:x :y :w :h`, optional `:radius` (rounded)
  `:circle`    — `:cx :cy :r`     `:ellipse` — `:cx :cy :rx :ry`
  `:arc` / `:wedge` — `:cx :cy :r :r-inner :start :end` (degrees)
  `:path`      — `:d` (SVG path data), `:fill-rule`
  `:text`      — `:text :x :y :anchor (:start|:middle|:end) :baseline :rotate`
  `:image`     — `:image` (an `Img`), `:x :y :w :h :opacity`

Returns `img`.
sourceraw docstring

encodeclj

(encode img)
(encode img fmt)
(encode img fmt quality)

Encode to fmt (:png :jpeg :webp :gif :bmp :tiff :ico :qoi :pnm :tga); returns a byte[]. quality (1-100, default 85) applies to the lossy formats.

Encode to `fmt` (`:png` `:jpeg` `:webp` `:gif` `:bmp` `:tiff` `:ico` `:qoi`
`:pnm` `:tga`); returns a byte[]. `quality` (1-100, default 85) applies to the
lossy formats.
sourceraw docstring

encode-gifclj

(encode-gif spec)

Encode an animated GIF from {:width :height :loop-count :frames}, each frame {:delay-ms :rgba} (straight RGBA8 byte[]). :loop-count -1/omitted = loop forever. Returns a byte[].

Encode an animated GIF from `{:width :height :loop-count :frames}`, each frame
`{:delay-ms :rgba}` (straight RGBA8 byte[]). `:loop-count` -1/omitted = loop
forever. Returns a byte[].
sourceraw docstring

flattenclj

(flatten img)
(flatten img bg)

Composite onto an opaque background (default white).

Composite onto an opaque background (default white).
sourceraw docstring

flipclj

(flip img mode)

:horizontal/:h or :vertical/:v.

`:horizontal`/`:h` or `:vertical`/`:v`.
sourceraw docstring

fontsclj

(fonts)

Every font family known to the shared font database, as a vector of strings. The four Noto faces (sans regular/bold/italic + mono) are embedded, so text and SVG rendering never depend on system fonts.

Every font family known to the shared font database, as a vector of strings.
The four Noto faces (sans regular/bold/italic + mono) are embedded, so text
and SVG rendering never depend on system fonts.
sourceraw docstring

from-pixelsclj

(from-pixels rgba w h)

An image from straight (non-premultiplied) RGBA8 rows — w*h*4 bytes.

An image from straight (non-premultiplied) RGBA8 rows — `w*h*4` bytes.
sourceraw docstring

get-pixelclj

(get-pixel img x y)

Packed 0xRRGGBBAA of one pixel, or nil when out of bounds.

Packed `0xRRGGBBAA` of one pixel, or nil when out of bounds.
sourceraw docstring

grayscaleclj

(grayscale img)
source

heightclj

(height img)
source

img?clj

(img? x)
source

infoclj

(info img)

{:width :height :is-opaque :is-grayscale} — read off the handle's own RGBA8 pixels (:is-grayscale = every pixel has r = g = b), not off the file it came from; probe answers that one.

`{:width :height :is-opaque :is-grayscale}` — read off the handle's own RGBA8
pixels (`:is-grayscale` = every pixel has r = g = b), not off the file it came
from; `probe` answers that one.
sourceraw docstring

invertclj

(invert img)
source

mp4?clj

(mp4? data)

True when data looks like an ISO-BMFF/MP4 container (a ftyp box at byte 4). A sniff, not a validation — probe-video is the one that reads tracks.

True when `data` looks like an ISO-BMFF/MP4 container (a `ftyp` box at byte
4). A sniff, not a validation — `probe-video` is the one that reads tracks.
sourceraw docstring

officeclj

(office kind spec)

Build an Office Open XML document from a declarative spec and return its bytes. kind is :xlsx, :docx or :pptx. Pure Rust — rust_xlsxwriter for workbooks, hand-written WordprocessingML/PresentationML for the rest; no POI, no JVM document model, and it works in a native image.

See xlsx, docx and pptx for the per-kind spec.

Build an Office Open XML document from a declarative spec and return its
bytes. `kind` is `:xlsx`, `:docx` or `:pptx`. Pure Rust — rust_xlsxwriter for
workbooks, hand-written WordprocessingML/PresentationML for the rest; no POI,
no JVM document model, and it works in a native image.

See `xlsx`, `docx` and `pptx` for the per-kind spec.
sourceraw docstring

optimizeclj

(optimize data)
(optimize data opts)

Shrink an ENCODED image with the real, format-specific optimisers — oxipng (filter/heuristic search, colour-type and palette reduction, optional zopfli) for PNG, jpegtran-style lossless metadata stripping for JPEG, and a differencing re-encoder (gifsicle's algorithm) for GIF. Takes and returns encoded bytes.

LOSSLESS unless you ask otherwise: the pixels of a PNG or a JPEG come back bit-identical unless :lossy, a :quality, a different :format, a :max-width/:max-height or an unmeetable :max-bytes licenses a re-encode.

Options: :format (default: keep the input's) :level 0-6 effort :lossy (palette-quantise PNG / re-encode JPEG) :colors :dither :quality :progressive :strip (default true) :background :max-width :max-height (downscale to fit, never enlarge) :max-bytes (keep trying until it fits) :force (return the optimised bytes even when they are bigger).

Returns a byte[] — the smaller of optimised and original unless :force.

Shrink an ENCODED image with the real, format-specific optimisers — oxipng
(filter/heuristic search, colour-type and palette reduction, optional zopfli)
for PNG, jpegtran-style lossless metadata stripping for JPEG, and a
differencing re-encoder (gifsicle's algorithm) for GIF. Takes and returns
encoded bytes.

LOSSLESS unless you ask otherwise: the pixels of a PNG or a JPEG come back
bit-identical unless `:lossy`, a `:quality`, a different `:format`, a
`:max-width`/`:max-height` or an unmeetable `:max-bytes` licenses a re-encode.

Options: `:format` (default: keep the input's) `:level` 0-6 effort
`:lossy` (palette-quantise PNG / re-encode JPEG) `:colors` `:dither`
`:quality` `:progressive` `:strip` (default true) `:background`
`:max-width` `:max-height` (downscale to fit, never enlarge)
`:max-bytes` (keep trying until it fits)
`:force` (return the optimised bytes even when they are bigger).

Returns a byte[] — the smaller of optimised and original unless `:force`.
sourceraw docstring

paste!clj

(paste! dst src x y)
(paste! dst src x y {:keys [blend] :or {blend true}})

Draw src into dst at (x,y), IN PLACE. :blend false replaces the destination pixels instead of alpha-compositing.

Draw `src` into `dst` at (x,y), IN PLACE. `:blend` false replaces the
destination pixels instead of alpha-compositing.
sourceraw docstring

pixelsclj

(pixels img)

The image's straight RGBA8 rows as a byte[].

The image's straight RGBA8 rows as a byte[].
sourceraw docstring

plotclj

(plot spec)

Render a plot specification to an image. See com.blockether.imaging.plot for the spec builders (line, bar, scatter, hist, pie, heatmap, …) and the full vocabulary.

Render a plot specification to an image. See `com.blockether.imaging.plot` for
the spec builders (`line`, `bar`, `scatter`, `hist`, `pie`, `heatmap`, …) and
the full vocabulary.
sourceraw docstring

pptxclj

(pptx spec)

A .pptx presentation as bytes (hand-written PresentationML).

{:width 12192000 :height 6858000 ; EMU, 16:9 by default :properties {…} :layouts [{:name "Title Slide" :type :title :placeholders [{:type :ctrTitle :idx 0 :left :top :width :height :size :align}]}] :slides [{:layout 0 :background "#ffffff" :notes "…" :shapes [{:kind :textbox|:auto|:picture|:table|:chart|:connector :left :top :width :height :rotation :preset :roundRect :fill "#3366cc" :line {:color :width} :image {:data <bytes> :crop {:left :top :right :bottom}} :chart {:type :column :title "Revenue" :categories ["Q1" "Q2"] :legend {:position :bottom} :series [{:name "Sales" :values [3 7] :fill "4472C4"}]} :text-frame {:paragraphs [{:align :level :bullet :runs [{:text "hi" :bold true :size 1800}]}]}}]}]}

A chart :type is one of :column :bar :line :area :pie :doughnut :radar :scatter :bubble plus the *-stacked / *-percent-stacked variants. Each chart becomes its own ppt/charts/chartN.xml part, so PowerPoint and python-pptx see a real chart rather than a picture of one.

Lengths are EMU (914400 per inch), font sizes centipoints (1800 = 18 pt) — exactly how python-pptx normalises its own Length/Pt values.

A `.pptx` presentation as bytes (hand-written PresentationML).

`{:width 12192000 :height 6858000            ; EMU, 16:9 by default
  :properties {…}
  :layouts [{:name "Title Slide" :type :title
             :placeholders [{:type :ctrTitle :idx 0
                             :left :top :width :height :size :align}]}]
  :slides [{:layout 0 :background "#ffffff" :notes "…"
            :shapes [{:kind :textbox|:auto|:picture|:table|:chart|:connector
                      :left :top :width :height :rotation
                      :preset :roundRect :fill "#3366cc" :line {:color :width}
                      :image {:data <bytes> :crop {:left :top :right :bottom}}
                      :chart {:type :column :title "Revenue"
                              :categories ["Q1" "Q2"]
                              :legend {:position :bottom}
                              :series [{:name "Sales" :values [3 7]
                                        :fill "4472C4"}]}
                      :text-frame {:paragraphs [{:align :level :bullet
                                                 :runs [{:text "hi" :bold true
                                                         :size 1800}]}]}}]}]}`

A chart `:type` is one of `:column :bar :line :area :pie :doughnut :radar
:scatter :bubble` plus the `*-stacked` / `*-percent-stacked` variants. Each
chart becomes its own `ppt/charts/chartN.xml` part, so PowerPoint and
`python-pptx` see a real chart rather than a picture of one.

Lengths are EMU (`914400` per inch), font sizes centipoints (`1800` = 18 pt) —
exactly how `python-pptx` normalises its own `Length`/`Pt` values.
sourceraw docstring

probeclj

(probe data)

Identify encoded bytes without a full decode: {:format :width :height :bytes :is-animated :frames :color :channels :bits :is-grayscale :has-alpha}. The colour keys describe the SOURCE file — a decoded Img is always RGBA8, so this is the only way to learn that a PNG was 8-bit grayscale (:color "l8") or 16-bit. :color is one of "l8" "la8" "rgb8" "rgba8" "l16" "la16" "rgb16" "rgba16" "rgb32f" "rgba32f"; indexed/palette sources report what they expand into. SVG documents report :format "svg" and rasterise as "rgba8".

Identify encoded bytes without a full decode:
`{:format :width :height :bytes :is-animated :frames :color :channels :bits
:is-grayscale :has-alpha}`. The colour keys describe the SOURCE file — a
decoded `Img` is always RGBA8, so this is the only way to learn that a PNG
was 8-bit grayscale (`:color "l8"`) or 16-bit. `:color` is one of `"l8"`
`"la8"` `"rgb8"` `"rgba8"` `"l16"` `"la16"` `"rgb16"` `"rgba16"`
`"rgb32f"` `"rgba32f"`; indexed/palette sources report what they expand
into. SVG documents report `:format "svg"` and rasterise as `"rgba8"`.
sourceraw docstring

probe-videoclj

(probe-video data)

Identify an MP4 without decoding a frame: {:format :codec :codec-kind :is-decodable :width :height :frames :duration-s :fps :timescale :has-audio}. :frames is the sample count and :width /:height the container's declared track size — the bitstream's own size is what decode-video reports. :is-decodable is false for a video track this build cannot decode (HEVC, AV1, VP9); only H.264/AVC decodes.

Identify an MP4 without decoding a frame:
`{:format :codec :codec-kind :is-decodable :width :height :frames :duration-s
:fps :timescale :has-audio}`. `:frames` is the sample count and `:width`
/`:height` the container's declared track size — the bitstream's own size is
what `decode-video` reports. `:is-decodable` is false for a video track this
build cannot decode (HEVC, AV1, VP9); only H.264/AVC decodes.
sourceraw docstring

put-pixel!clj

(put-pixel! img x y c)
source

quantizeclj

(quantize img)
(quantize img {:keys [colors dither] :or {colors 256 dither false}})

Median-cut colour quantisation with optional Floyd-Steinberg dithering — the palette engine behind optimize's lossy PNG and GIF paths.

Returns {:width :height :palette :indices :transparent :rgba}: :palette a vector of 0xRRGGBB ints, :indices one palette index per pixel (byte[]), :transparent the palette slot used for fully transparent pixels (or nil), :rgba the quantised image back as straight RGBA8 rows.

Median-cut colour quantisation with optional Floyd-Steinberg dithering — the
palette engine behind `optimize`'s lossy PNG and GIF paths.

Returns `{:width :height :palette :indices :transparent :rgba}`: `:palette` a
vector of `0xRRGGBB` ints, `:indices` one palette index per pixel (byte[]),
`:transparent` the palette slot used for fully transparent pixels (or nil),
`:rgba` the quantised image back as straight RGBA8 rows.
sourceraw docstring

rank-filterclj

(rank-filter img size rank)

Per-channel rank filter over an odd size x size window: every channel (alpha included) is sorted independently and the rank-th smallest kept. :min / :median / :max are the named ranks — Pillow's MinFilter, MedianFilter and MaxFilter; an integer picks the rank directly.

Per-channel rank filter over an odd `size` x `size` window: every channel
(alpha included) is sorted independently and the `rank`-th smallest kept.
`:min` / `:median` / `:max` are the named ranks — Pillow's `MinFilter`,
`MedianFilter` and `MaxFilter`; an integer picks the rank directly.
sourceraw docstring

read-officeclj

(read-office data)
(read-office data opts)

Read an Office document back. Workbooks (.xlsx .xlsm .xlsb .xls .ods) come back as {:kind :sheets [{:name :rows [[cell …] …]}]} with cells already coerced to strings/numbers/booleans; .docx comes back as {:kind :paragraphs [...]}.

A .pptx is read back as the mirror image of what pptx writes — the whole DrawingML shape tree, not just its text:

{:kind :width :height :properties :slides [{:name :index :layout :notes :paragraphs :shapes [{:kind :name :left :top :width :height :rotation :text-frame {…} :table {…} :chart {…} :image {…}}]}]}

so a deck can be read, edited and written again without losing its shapes.

Options: :sheet (name or index — read just that one), :header (treat the first row as keys and return maps), :max-rows, and :with-images (base64 every embedded picture of a presentation; off by default).

Read an Office document back. Workbooks (`.xlsx` `.xlsm` `.xlsb` `.xls`
`.ods`) come back as `{:kind :sheets [{:name :rows [[cell …] …]}]}` with cells
already coerced to strings/numbers/booleans; `.docx` comes back as
`{:kind :paragraphs [...]}`.

A `.pptx` is read back as the mirror image of what `pptx` writes — the whole
DrawingML shape tree, not just its text:

`{:kind :width :height :properties
  :slides [{:name :index :layout :notes :paragraphs
            :shapes [{:kind :name :left :top :width :height :rotation
                      :text-frame {…} :table {…} :chart {…} :image {…}}]}]}`

so a deck can be read, edited and written again without losing its shapes.

Options: `:sheet` (name or index — read just that one), `:header` (treat the
first row as keys and return maps), `:max-rows`, and `:with-images` (base64
every embedded picture of a presentation; off by default).
sourceraw docstring

register-font!clj

(register-font! font)

Add a TTF/OTF/TTC (bytes/File/path/stream) to the font database for this process; returns the vector of families it provided.

Add a TTF/OTF/TTC (bytes/File/path/stream) to the font database for this
process; returns the vector of families it provided.
sourceraw docstring

render-svgclj

(render-svg svg)
(render-svg svg opts)

Rasterise an SVG/SVGZ document (bytes, markup String, File, path, stream) with resvg. Options: :width :height :scale :max-width :max-height :background :dpi :font-family :font-size :base-url.

The canvas is REPAIRED by default: a document with a zero, negative or absent size is sized the way a BROWSER would (see svg-canvas) instead of failing resvg's size check. Pass :repair false for resvg's literal answer.

Rasterise an SVG/SVGZ document (bytes, markup String, File, path, stream) with
resvg. Options: `:width` `:height` `:scale` `:max-width` `:max-height`
`:background` `:dpi` `:font-family` `:font-size` `:base-url`.

The canvas is REPAIRED by default: a document with a zero, negative or absent
size is sized the way a BROWSER would (see `svg-canvas`) instead of failing
resvg's size check. Pass `:repair false` for resvg's literal answer.
sourceraw docstring

resizeclj

(resize img w h)
(resize img w h filter)

Resample to exactly w x h. filter: :nearest :triangle/:bilinear :catmullrom/:bicubic :gaussian :lanczos3 (default), passed through.

Resample to exactly `w` x `h`. `filter`: `:nearest` `:triangle`/`:bilinear`
`:catmullrom`/`:bicubic` `:gaussian` `:lanczos3` (default), passed through.
sourceraw docstring

rotateclj

(rotate img degrees)
(rotate img degrees {:keys [expand background]})

Rotate counter-clockwise by degrees. :expand true grows the canvas to hold the rotated image; :background fills behind it.

Rotate counter-clockwise by `degrees`. `:expand` true grows the canvas to hold
the rotated image; `:background` fills behind it.
sourceraw docstring

save!clj

(save! img file)
(save! img file {:keys [format quality] :as _opts})

Encode img and write it to file; the format comes from the extension unless :format says otherwise. Returns the file.

Encode `img` and write it to `file`; the format comes from the extension
unless `:format` says otherwise. Returns the file.
sourceraw docstring

svg-canvasclj

(svg-canvas svg)
(svg-canvas svg opts)

How a BROWSER would size an SVG/SVGZ document (bytes, markup String, File, path, stream): {:width :height :source :is-repaired :svg}.

resvg answers only for documents that declare a usable size: it refuses a zero or negative one, and measures a size-less document from the ORIGIN, so a figure drawn at x=50 gets 50px of dead margin. A browser falls back to the viewBox, then to the ink actually painted. :source says which rule won — "declared" (resvg's own resolved size), "view_box", "content" or "default" — and :svg is the REPAIRED markup (a byte[], nil when the document needed no repair), which render-svg/decode rasterise as drawn.

render-svg with :repair true does exactly this internally. Options: :min-dimension (512) and :max-dimension (4096) bound an ink-framed canvas, plus the parse options of render-svg.

How a BROWSER would size an SVG/SVGZ document (bytes, markup String, File,
path, stream): `{:width :height :source :is-repaired :svg}`.

resvg answers only for documents that declare a usable size: it refuses a zero
or negative one, and measures a size-less document from the ORIGIN, so a
figure drawn at x=50 gets 50px of dead margin. A browser falls back to the
`viewBox`, then to the ink actually painted. `:source` says which rule won —
`"declared"` (resvg's own resolved size), `"view_box"`, `"content"` or
`"default"` — and `:svg` is the REPAIRED markup (a byte[], nil when the
document needed no repair), which `render-svg`/`decode` rasterise as drawn.

`render-svg` with `:repair true` does exactly this internally. Options:
`:min-dimension` (512) and `:max-dimension` (4096) bound an ink-framed canvas,
plus the parse options of `render-svg`.
sourceraw docstring

text-measureclj

(text-measure spec)

Measure a text run without drawing it — same :text :size :family :weight :italic :letter-spacing :line-height keys as the :text draw op. Returns {:width :height :x :y :lines}, the ink box relative to the first baseline.

Measure a text run without drawing it — same `:text :size :family :weight
:italic :letter-spacing :line-height` keys as the `:text` draw op. Returns
`{:width :height :x :y :lines}`, the ink box relative to the first baseline.
sourceraw docstring

thumbnailclj

(thumbnail img max-w max-h)

Scale DOWN to fit inside max-w x max-h, preserving aspect ratio.

Scale DOWN to fit inside `max-w` x `max-h`, preserving aspect ratio.
sourceraw docstring

versionclj

(version)

The cdylib's version string (crate version + backing engines).

The cdylib's version string (crate version + backing engines).
sourceraw docstring

video->gifclj

(video->gif data)
(video->gif data opts)

Transcode an MP4 straight to an animated GIF byte[] — the frames never cross the FFI boundary, so this is the cheap way to make a clip watchable anywhere a GIF is (a terminal, a chat wire that allows image/gif, a browser).

Options: the decode-video ones (:max-frames :stride :max-dimension :filter) plus :fps (playback rate; default the source rate divided by :stride) and :loop-count (-1/omitted = forever). GIF stores its delay in CENTIseconds, so the frame rate is quantised to 1/100 s.

Transcode an MP4 straight to an animated GIF byte[] — the frames never cross
the FFI boundary, so this is the cheap way to make a clip watchable anywhere
a GIF is (a terminal, a chat wire that allows `image/gif`, a browser).

Options: the `decode-video` ones (`:max-frames` `:stride` `:max-dimension`
`:filter`) plus `:fps` (playback rate; default the source rate divided by
`:stride`) and `:loop-count` (-1/omitted = forever). GIF stores its delay in
CENTIseconds, so the frame rate is quantised to 1/100 s.
sourceraw docstring

widthclj

(width img)
source

xlsxclj

(xlsx spec)

A .xlsx workbook as bytes, written by rust_xlsxwriter.

{:properties {:title :subject :author :manager :company :category :keywords :comments :status} :sheets [{:name "Sales" :columns [{:first 0 :last 3 :width 18 :format {…} :hidden false}] :rows [{:index 0 :height 22 :format {…}}] :freeze [row col] :autofilter [r1 c1 r2 c2] :merges [{:range [r1 c1 r2 c2] :value … :format {…}}] :images [{:row :col :data <bytes> :scale-x :scale-y}] :cells [{:row 0 :col 0 :value "Region" :format {:bold true}}]}]}

A cell's :type is optional — a string/number/boolean/nil is written as itself; the explicit types are string number boolean formula datetime date time url blank and rich (a run list of [format? text]). A :format map (:bold :italic :underline :font :size :color :bg-color :align :valign :wrap :rotation :indent :border :num-format :locked …) is deduplicated into one workbook format automatically.

A `.xlsx` workbook as bytes, written by rust_xlsxwriter.

`{:properties {:title :subject :author :manager :company :category :keywords
               :comments :status}
  :sheets [{:name "Sales"
            :columns [{:first 0 :last 3 :width 18 :format {…} :hidden false}]
            :rows [{:index 0 :height 22 :format {…}}]
            :freeze [row col] :autofilter [r1 c1 r2 c2]
            :merges [{:range [r1 c1 r2 c2] :value … :format {…}}]
            :images [{:row :col :data <bytes> :scale-x :scale-y}]
            :cells [{:row 0 :col 0 :value "Region" :format {:bold true}}]}]}`

A cell's `:type` is optional — a string/number/boolean/nil is written as
itself; the explicit types are `string` `number` `boolean` `formula`
`datetime` `date` `time` `url` `blank` and `rich` (a run list of
`[format? text]`). A `:format` map (`:bold :italic :underline :font :size
:color :bg-color :align :valign :wrap :rotation :indent :border :num-format
:locked` …) is deduplicated into one workbook format automatically.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close