/ concept-collection / numbl-image-filter
Sign in
concept-collection / numbl-image-filter
numbl-image-filter / README.md
81 lines · 2.9 KBPreviewCodeBlameHistoryRaw
1# numbl image filter
3A small web app that filters an image using a **[numbl](https://numbl.org)** script
4(MATLAB syntax), running entirely in your browser. Pick a built-in sample or upload
5your own image, write a filter function, and see the original and filtered images
6side by side.
8It uses [numbl](https://www.npmjs.com/package/numbl) as a library: the image is
9handed to the script as a tensor and the script's output tensor is drawn back to a
10canvas.
12## Quick start
14```bash
15npm install
16npm run dev
17```
19Then open the printed URL.
21```bash
22npm run build # type-check + production build to dist/
23npm run preview # serve the production build
24```
26## How the filter works
28You write a function `filterImage` (MATLAB syntax). It receives the image and
29returns a new one:
31```matlab
32function out = filterImage(img)
33 % img : H x W x 3 array of doubles in [0, 255] (RGB)
34 % out : H x W x 3 (color) or H x W (grayscale) in [0, 255]
35 out = 255 - img; % invert
36end
37```
39- `img(:,:,1)`, `img(:,:,2)`, `img(:,:,3)` are the R, G, B planes.
40- Returning an `H x W` (2-D) array gives a grayscale result.
41- Output values are clamped to `[0, 255]` when displayed.
42- The function name doesn't have to be `filterImage` — the app calls whatever
43 function the script defines. (A script with no `function` header is run as-is
44 with `img` predefined and `out` read back.)
46Use the **Example** dropdown for ready-made filters: grayscale, sepia, posterize,
47contrast, channel swap, Sobel edges, box blur, and more.
49## How it's wired
51```
52upload / sample image
53 │ decode to RGBA (canvas)
54
55RGBA bytes ── rgbaToTensorData ──► [H,W,3] doubles (column-major, 0-255)
56
57Web Worker: executeCode("out = filterImage(img);", { initialVariableValues: { img } })
58
59out tensor ── tensorToRaw ──► RGBA bytes ──► canvas
60```
62- Marshaling lives in [`src/imageConvert.ts`](src/imageConvert.ts). numbl tensors are
63 **column-major**; browser `ImageData` is row-major RGBA — the conversion handles both.
64- The filter runs in a [Web Worker](src/filter.worker.ts) (`numbl`'s `executeCode` at
65 optimization `"1"`, the JS-JIT, which is browser-safe) so full-resolution images with
66 per-pixel scripts don't freeze the page.
68## Images
70Everything runs locally — there are **no remote images**. Two sources:
72- **Generated** patterns (RGB gradient, shapes, checkerboard) created in the browser
73 ([`src/synthetic.ts`](src/synthetic.ts) / [`src/samples.ts`](src/samples.ts)).
74- **Your uploads**, which are saved to **IndexedDB** and persist across sessions.
75 They appear under "Your images" in the picker; each can be deleted with the × button.
76 Storage lives in [`src/imageStore.ts`](src/imageStore.ts) (the original compressed
77 file Blob + a small thumbnail are stored; the full image is decoded on demand).
79## License
81Apache-2.0 (matching numbl). Sample photos are CC0 / public domain from Wikimedia Commons.
moveopenescclose