Conversation
setup library for image processing and add few util functions add unit test for process function
image-fn.mp4 |
|
Hiya @josephjclark i have added
|
jimp |
@jsquash |
|
|---|---|---|
| Output size (q80) | ~389KB | ~312KB (–20%) |
| Input formats | JPEG, PNG, BMP, GIF, TIFF | JPEG only |
| Setup cost | None | ~200ms WASM init |
| Compression loop | 4170ms | 2512ms (40% faster) |
For this use case (single CommCare JPEG per job): differences are minor. @jsquash wins on compression efficiency; jimp wins on format flexibility.
⚠️ If we ever need to accept PNGs or screenshots,@jsquashthrows at runtime
I think the right choice depends on use case. But i will pick jimp over @jsquash because of multiple image support and simple implementation. @jsquash wasmBinary feels a bit complicated to tbh
|
@mtuchi Please see my earlier comment about the design of the adaptor. Need to get that right before I can look closer |
…ompress() Drop wasm dependencies (@jsquash/jpeg, @jsquash/resize) in favour of jimp-only pipeline. Split the combined process() into two composable operations — resize() and compress() — each accepting an explicit base64 string or Buffer. Keep process() as a backward-compatible wrapper. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Lets call it image-utils |
Rename adaptor to @openfn/language-image-utils. Drop the combined process() function in favour of four focused utilities — strip() removes EXIF metadata explicitly, metadata() exposes dimensions/orientation/size for job-code validation, toBase64() and toBuffer() handle buffer/string conversion and enable passing buffers between steps. Remove gif and avif test fixtures. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ction
Remove standalone toBase64/toBuffer operations. All image functions
(resize, compress, strip) now accept a base64: true option — when set
the output buffer key is replaced with a base64 string. Uses
buffer.toString('base64') directly since util.encode is text/JSON-
oriented and not suitable for binary image data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace { base64: true } with { parseAs: 'base64' } on resize, compress,
and strip to match the parseAs convention used in language-common http.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add annotate(input, { comment }) for embedding EXIF UserComment data.
Remove the comment option from compress() — compression and metadata
writing are separate concerns.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Hiya @josephjclark i have addressed you're early feedback and cleanup .avi and .gif images, i will wait for you're feedback before cleaning up more images |
| * @state {ImageState} | ||
| * @returns {Operation} | ||
| */ | ||
| export function resize(base64ImgOrBuffer, options = {}) { |
There was a problem hiding this comment.
Why resize(image, options) and not resize(image, width, height)? What do we gain with the options object?
There was a problem hiding this comment.
@josephjclark in options we have parseAs option which is by default set to buffer.
But there are couple of other benefits like if we decide to add other options like,fit for managing fit image aspect ration, or quality to control image quality
Should we consider
resize(image, width, height, options)
OR
resize(image, dimensions ={width, height}, options= {parseAs})
|
Hiya @josephjclark i have added some integration test based on recent feedback from @jfeldman-openfn, See justin comment here. I would love you're feedback when you get back |
Summary
New
@openfn/language-image-utilsadaptor providing image processing utilities for OpenFn job code.Details
Using joe's implementation i was able to do the following
Five exported operations, each accepting a
base64 string,data URL, orBufferas input:-
resize(input, { width, height })— resizes to target dimensions usingjimp; outputs { buffer, width, height }-
compress(input, { maxBytes, minQuality })— quality-loop compression to a byte target; outputs{ buffer, size, quality }-
stripMetadata(input)— strips all EXIF metadata (including GPS) by re-encoding through Jimp; outputs{ buffer }-
embedMetadata(input, { comment })— embeds a string in the JPEG EXIF UserComment field; outputs{ buffer }-
metadata(input)— reads image dimensions and orientation without modifying the image; outputs{ width, height, orientation, size }{ parseAs: 'base64' }to return abase64 stringinstead of aBuffer, similar toparseAsconvention inlanguage-commonjimppackage. Thepiexifjspackage is used only forEXIF UserCommentinjection inannotatefunctionHere is sample job code
AI Usage
Please disclose how you've used AI in this work (it's cool, we just want to
know!):
You can read more details in our
Responsible AI Policy
Review Checklist
Before merging, the reviewer should check the following items:
production? Is it safe to release?
dev only changes don't need a changeset.