image
Image processing domain adapter — real raster pixel work via sharp (libvips): resize/crop/fit, format convert, compress, thumbnail, rotate/flip, grayscale/blur/sharpen/tint/negate/modulate, composite...
image — raster image processing adapter
Real image processing for the Leumas ecosystem, powered by sharp (libvips). Every tool takes a single args object (so an HTTP POST body maps 1:1) and returns a plain JSON-serializable result. Inputs accept a base64 string (raw or a data:image/...;base64, URI) or a local file path; outputs return a base64-encoded image plus format/width/height.
Contract: export default { metadata, adapters: { <tool>: async (args) => result } }.
Lazy-guarded native dependency
sharp is a native (libvips) module. It is imported lazily and guarded: the pack always loads, even on a machine where sharp failed to install/compile. In that case every tool returns:
{ "ok": false, "unavailable": true, "error": "sharp not installed: ..." }
so callers can degrade gracefully instead of the whole registry failing to load. On success each processing tool returns { ok:true, base64, format, width, height, channels, size, mime }. Pass dataUri:true in args to get a ready-to-embed data:image/...;base64,... string instead of raw base64.
Tools
| Tool | What it does |
|---|---|
resize | Resize to exact width/height (omit one to keep aspect ratio). Optional fit. |
crop | Extract a width×height region at left/top. |
resizeToFit | Fit into a box with fit = contain (pad) / cover (crop) / fill / inside / outside. |
convert | Re-encode to format = jpeg/png/webp/avif/tiff/gif, optional quality. |
compress | Re-encode at a lower quality (default 60) to shrink size; keeps input format by default. |
thumbnail | Cover-cropped thumbnail at size (default 128), webp by default. |
rotate | Rotate by angle degrees (default 90); non-90° fills corners with background. |
flip | Mirror vertically. |
flop | Mirror horizontally. |
grayscale | Desaturate to grayscale. |
blur | Gaussian blur (sigma, default 3). |
sharpen | Sharpen (sigma, default 1). |
tint | Tint toward a color (hex or CSS name). |
negate | Photographic negative (alpha:true also inverts alpha). |
modulate | Adjust brightness/saturation/hue/lightness. |
gamma | Gamma correction (gammaValue 1.0–3.0). |
normalize | Auto-stretch contrast. |
extend | Pad a border (all or top/bottom/left/right) with background. |
trim | Trim uniform border pixels. |
extractChannel | Extract channel red/green/blue/alpha (or 0-3) as grayscale. |
composite | Overlay a watermark/logo (overlay) with position/blend/opacity. |
flatten | Flatten transparency onto a solid background. |
metadata | Read width/height/format/channels/space/hasAlpha/orientation without re-encoding. |
stats | Per-channel min/max/mean/stdev + isOpaque/entropy/dominant. |
dominantColor | Dominant colour as {r,g,b} + #hex. |
stripExif | Re-encode without EXIF/metadata (bakes in orientation first). |
toBase64 | Normalize any accepted input to base64 (optionally a data URI / target format). |
Usage
import image from './index.js';
// Make a 128px webp thumbnail from a file path:
const thumb = await image.adapters.thumbnail({ image: 'C:/photos/cat.jpg', size: 128 });
// → { ok:true, base64:'...', format:'webp', width:128, height:128, ... }
// Convert an inline base64 PNG to a compressed JPEG data URI:
const jpg = await image.adapters.convert({ image: pngB64, format: 'jpeg', quality: 70, dataUri: true });
// Watermark: overlay a logo bottom-right at 50% opacity:
await image.adapters.composite({ image: photoB64, overlay: logoB64, position: 'southeast', opacity: 0.5 });
// Inspect without decoding a full re-encode:
await image.adapters.metadata({ image: 'C:/photos/cat.jpg' });
DRY boundary
- vs
a-transformation— a-transformation only reads an image's basename / statInfo (the
filename string + fs stat metadata: size, mtime, path parts). That is filesystem/string work, not pixels. This image pack does the actual pixel decoding & processing via sharp. No overlap — a filename helper stays in a-transformation; anything touching pixels lives here.
- vs
numbers—numbers.baseConvertis integer radix conversion; the base64 in this pack is
binary image encoding. Different concerns.
- Self-contained: no cross-pack imports.
sharpis the only external dependency (declared in the local
package.json for provenance; installed at the workspace root).