numbl image filter#
A small web app that filters an image using a numbl script (MATLAB syntax), running entirely in your browser. Pick a built-in sample or upload your own image, write a filter function, and see the original and filtered images side by side.
It uses numbl as a library: the image is handed to the script as a tensor and the script's output tensor is drawn back to a canvas.
Quick start#
npm install
npm run dev
Then open the printed URL.
npm run build # type-check + production build to dist/
npm run preview # serve the production build
How the filter works#
You write a function filterImage (MATLAB syntax). It receives the image and
returns a new one:
function out = filterImage(img)
% img : H x W x 3 array of doubles in [0, 255] (RGB)
% out : H x W x 3 (color) or H x W (grayscale) in [0, 255]
out = 255 - img; % invert
end
img(:,:,1),img(:,:,2),img(:,:,3)are the R, G, B planes.- Returning an
H x W(2-D) array gives a grayscale result. - Output values are clamped to
[0, 255]when displayed. - The function name doesn't have to be
filterImage— the app calls whatever function the script defines. (A script with nofunctionheader is run as-is withimgpredefined andoutread back.)
Use the Example dropdown for ready-made filters: grayscale, sepia, posterize, contrast, channel swap, Sobel edges, box blur, and more.
How it's wired#
upload / sample image
│ decode to RGBA (canvas)
▼
RGBA bytes ── rgbaToTensorData ──► [H,W,3] doubles (column-major, 0-255)
▼
Web Worker: executeCode("out = filterImage(img);", { initialVariableValues: { img } })
▼
out tensor ── tensorToRaw ──► RGBA bytes ──► canvas
- Marshaling lives in
src/imageConvert.ts. numbl tensors are column-major; browserImageDatais row-major RGBA — the conversion handles both. - The filter runs in a Web Worker (
numbl'sexecuteCodeat optimization"1", the JS-JIT, which is browser-safe) so full-resolution images with per-pixel scripts don't freeze the page.
Images#
Everything runs locally — there are no remote images. Two sources:
- Generated patterns (RGB gradient, shapes, checkerboard) created in the browser
(
src/synthetic.ts/src/samples.ts). - Your uploads, which are saved to IndexedDB and persist across sessions.
They appear under "Your images" in the picker; each can be deleted with the × button.
Storage lives in
src/imageStore.ts(the original compressed file Blob + a small thumbnail are stored; the full image is decoded on demand).
License#
Apache-2.0 (matching numbl). Sample photos are CC0 / public domain from Wikimedia Commons.