Compress, resize, crop, convert, watermark, annotate, pick colours, extract palettes, build collages and pixelate — instantly, on-device, with no network call and no data leaving your machine. One Rust core, one package, bindings for JavaScript, Python and Rust, plus a CLI.
npm install dusrelimageimport { compressImage } from 'dusrelimage';
const out = compressImage(input, { quality: 70 }); // Uint8Array out
console.log(out.length);from dusrelimage import compress_image
out = compress_image(data, quality=70) # bytes outCompress, resize, crop, convert, watermark, annotate, colour picker, palette, collage, pixelate. No per-feature subpackages.
No API keys, no network calls, no per-image fees. Works in a Lambda, a CLI, or a browser with no internet. Your photos never leave the machine.
One implementation, one test suite — the same rules in JavaScript, Python and Rust. No drift between ports, same answer everywhere.
Every failure carries a stable code plus message_en and message_hi, so your error messages make sense to every user.
Options everywhere: quality, fit modes, filters, positions, opacity, rotation, EXIF handling, size limits — a real control layer, not presets.
dusrelimage compress, resize, watermark, palette, collage … with --json output for scripts.
Every operation takes bytes and returns bytes. No temp files, no shared state — steps compose like a pipeline.
The real Rust core compiled to WASM. Your files never leave the browser — try it before installing anything.
| Tool | What it does | Example |
|---|---|---|
| Compress | Shrink file size at a quality, or to an exact target size | compressImage(img, { quality: 70 }) |
| Resize | New width / height / percent, fit modes, filters | resizeImage(img, { width: 800 }) |
| Crop | Cut a rectangle, or an anchor preset | cropImage(img, { width: 500, height: 500, anchor: 'Center' }) |
| Convert | Change format — JPEG, PNG, WebP, AVIF, GIF, BMP | convertImage(img, { format: 'WebP' }) |
| Watermark | Text or logo stamp, 9 anchors + tiled | addWatermark(img, { text: { text: '© dusrel' } }) |
| Annotate | Arrows, rectangles, ellipses, lines, text | annotateImage(img, [{ type: 'Arrow', … }]) |
| Colour picker | The exact colour of one pixel — hex, RGB, HSL | pickColour(img, 120, 80) |
| Palette | Dominant colours, most frequent first | extractPalette(img, 5) |
| Collage | Several images into one grid / row / column | makeCollage([a, b, c, d], { layout: '2x2' }) |
| Pixelate | Mosaic-blur a rectangle (faces, plates) | pixelateImage(img, { x: 100, y: 80, width: 120, height: 120, blockSize: 16 }) |
| Code | Means |
|---|---|
INVALID_IMAGE | Input is not an image, is truncated, or cannot be decoded |
UNSUPPORTED_FORMAT | Format recognised but not supported for this operation |
IMAGE_TOO_LARGE | Over the max_pixels limit (default 120,000,000) |
TARGET_SIZE_UNREACHABLE | Even the lowest quality exceeds the target size |
CROP_OUT_OF_BOUNDS | Crop rectangle sticks out of the image |
PIXEL_OUT_OF_BOUNDS | Picked pixel is outside the image |
INVALID_QUALITY | Quality outside 1–100 |
INVALID_DIMENSIONS | Bad or missing dimensions, or a side over the limit |
INVALID_ARGUMENT | Bad argument (opacity, block size, bad layout, …) |
EMPTY_INPUT | Empty input list / byte buffer where one item is required |
INVALID_TYPE | Wrong value type reached a bindings API |
Branch on code, never on the message text. Every failure also carries a Hindi message (message_hi). Full error-code table →
v0.1.0 has no HEIC support and doesnot stream — the whole image lives in memory.
IMAGE_TOO_LARGE.