From 4f47ccbcff99f4fcada2bf941a84141c8e3f01f3 Mon Sep 17 00:00:00 2001 From: Krasner Date: Wed, 20 May 2026 20:34:33 +0000 Subject: [PATCH 01/11] generated docs with codex --- core/include/img2num.h | 1 - docs/docs/api-reference.md | 54 ++++++++++++ docs/docs/c/api-reference.md | 140 +++++++++++++++++++++++++----- docs/docs/c/docs/index.md | 54 ++++++++++-- docs/docs/concepts.md | 58 +++++++++++++ docs/docs/cpp/api-reference.md | 124 +++++++++++++++++++++----- docs/docs/cpp/docs/index.md | 66 ++++++++++++-- docs/docs/getting-started.md | 87 +++++++++++++++++++ docs/docs/index.md | 27 ++++-- docs/docs/installation.md | 89 +++++++++++++++++++ docs/docs/js/api-reference.md | 76 ++++++++++++++++ docs/docs/js/docs/index.md | 70 +++++++++++++-- docs/docs/performance.md | 50 +++++++++++ docs/docs/python/api-reference.md | 73 ++++++++++++++++ docs/docs/python/index.md | 55 ++++++++++++ docs/docs/troubleshooting.md | 55 ++++++++++++ 16 files changed, 1005 insertions(+), 74 deletions(-) create mode 100644 docs/docs/api-reference.md create mode 100644 docs/docs/concepts.md create mode 100644 docs/docs/getting-started.md create mode 100644 docs/docs/installation.md create mode 100644 docs/docs/js/api-reference.md create mode 100644 docs/docs/performance.md create mode 100644 docs/docs/python/api-reference.md create mode 100644 docs/docs/python/index.md create mode 100644 docs/docs/troubleshooting.md diff --git a/core/include/img2num.h b/core/include/img2num.h index 97d361a17..90e48bc9a 100644 --- a/core/include/img2num.h +++ b/core/include/img2num.h @@ -18,7 +18,6 @@ namespace img2num { /// @brief Configuration options for image_to_svg. /// @ingroup IMG2NUM_H struct ImageToSvgConfig { - /// Configuration settings for the bilateral filter in image_to_svg. struct BilateralFilterConfig { /// Standard deviation for spatial Gaussian (proximity weight). diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md new file mode 100644 index 000000000..e02aa2fb1 --- /dev/null +++ b/docs/docs/api-reference.md @@ -0,0 +1,54 @@ +--- +id: api-reference +title: API Reference Overview +sidebar_position: 6 +--- + +# API Reference Overview + +Img2Num provides bindings for multiple languages. Choose the one that fits your workflow: + +| Language | Docs | +| :--- | :--- | +| **JavaScript** | [JS API Reference](./js/api-reference) | +| **C++** | [C++ API Reference](./cpp/api-reference) | +| **C** | [C API Reference](./c/api-reference) | +| **Python** | [Python API Reference](./python/api-reference) | + +## Common Concepts Across All Bindings + +All APIs share these core concepts: + +1. **Bilateral Filtering** — Smooths noise while preserving edges. +2. **K-Means Clustering** — Reduces the palette to `k` representative colors. +3. **Contour Tracing** — Detects boundaries between color clusters. +4. **B-spline Simplification** — Fits smooth quadratic curves to contours. + +## Shared Parameters + +| Parameter | Type | Default | Description | +| :--- | :--- | :--- | :--- | +| `sigma_spatial` | `float` | `3` | Bilateral spatial sigma | +| `sigma_range` | `float` | `50` | Bilateral range sigma | +| `num_colors` / `k` | `int` | `16` | Number of clusters | +| `max_iter` | `int` | `100` | K-means iterations | +| `min_area` | `int` | `100` | Minimum contour area | +| `color_space` | `int` | `0` | `0` = CIE LAB, `1` = sRGB | + +## Pipeline Flow + +``` +[Raster Image] + │ + ▼ +[ Bilateral Filter ] (sigma_spatial, sigma_range) + │ + ▼ +[ K-Means Clustering ] (k, max_iter, color_space) + │ + ▼ +[ Contour Detection ] (min_area) + │ + ▼ +[ SVG Output ] +``` diff --git a/docs/docs/c/api-reference.md b/docs/docs/c/api-reference.md index 150bf2f8c..64710d39e 100644 --- a/docs/docs/c/api-reference.md +++ b/docs/docs/c/api-reference.md @@ -1,31 +1,127 @@ --- +id: c-api-reference title: C API Reference -description: > - This page provides a full-page view of the Img2Num's C API reference - generated by Doxygen. Use the fullscreen button to expand the view - for easier navigation and code browsing. +sidebar_position: 1 --- -import FullscreenIframe from "@site/src/components/FullscreenIframe"; - -export const DocsLink = () => ( - { - e.preventDefault(); - window.location.href = "/Img2Num/info/docs/c/api/"; - }} - > - {" "} - Doxygen documentation{" "} - +# C API Reference + +The C API is declared in `cimg2num.h` and uses the `img2num_` prefix for all symbols. + +## Types + +### `img2num_ImageToSvgConfig` + +```c +typedef struct img2num_ImageToSvgConfig { + struct { + double sigma_spatial; + double sigma_range; + } bilateral_filter; + + struct { + int32_t k; + int32_t max_iter; + } kmeans; + + int min_cluster_area; + uint8_t color_space; +} img2num_ImageToSvgConfig; +``` + +### `img2num_ImageToSvgConfig_default()` + +Returns a config struct with all default values. + +## Functions + +### `img2num_gaussian_blur_fft` + +```c +void img2num_gaussian_blur_fft(uint8_t *image, size_t width, size_t height, double sigma); +``` + +Applies a Gaussian blur using FFT. + +### `img2num_invert_image` + +```c +void img2num_invert_image(uint8_t *ptr, int width, int height); +``` + +Inverts pixel values in-place. + +### `img2num_threshold_image` + +```c +void img2num_threshold_image(uint8_t *ptr, int width, int height, int num_thresholds); +``` + +Reduces the image to `num_thresholds` discrete levels. + +### `img2num_black_threshold_image` + +```c +void img2num_black_threshold_image(uint8_t *ptr, int width, int height, int num_thresholds); +``` + +Bias-weighted thresholding toward darker output. + +### `img2num_kmeans` + +```c +void img2num_kmeans( + const uint8_t *data, + uint8_t *out_data, + int32_t *out_labels, + int32_t width, + int32_t height, + int32_t k, + int32_t max_iter, + uint8_t color_space +); +``` + +K-means color clustering. + +### `img2num_bilateral_filter` + +```c +void img2num_bilateral_filter( + uint8_t *image, + size_t width, + size_t height, + double sigma_spatial, + double sigma_range, + uint8_t color_space +); +``` + +Edge-preserving bilateral smoothing. + +### `img2num_labels_to_svg` + +```c +char *img2num_labels_to_svg( + const uint8_t *data, + const int32_t *labels, + int width, + int height, + int min_area ); +``` -> Don't like iframes? -> Visit the{' '} directly. +Converts a labeled region map to SVG. Caller is responsible for `free()`ing the result. - +### `img2num_image_to_svg` -## About this page +```c +char *img2num_image_to_svg( + const uint8_t *data, + int width, + int height, + const img2num_ImageToSvgConfig *config +); +``` -This page is a direct proxy for the{' '} { e.preventDefault(); window.location.href = "/Img2Num/info/docs/c/api/"; }}> Doxygen documentation generated from the C core directory. +Full raster-to-SVG pipeline. Caller is responsible for `free()`ing the result. diff --git a/docs/docs/c/docs/index.md b/docs/docs/c/docs/index.md index 8d1b5a357..c7f537727 100644 --- a/docs/docs/c/docs/index.md +++ b/docs/docs/c/docs/index.md @@ -1,12 +1,50 @@ -# Docs +# C Binding Documentation -import Hedgehog from "@site/src/components/Hedgehog"; +The C bindings (`cimg2num.h`) expose the Img2Num library as plain C functions. This is useful for: -:::danger Help Wanted! -We need help with writing manual docs. -If you're interested, please see the [contributing guide](../../contributing) first. +- Embedding Img2Num in C projects +- Writing custom FFI wrappers +- Minimal overhead in systems programming - -::: +## Installation -> You don't need an issue to work on this - just mention it in your PR body.🦔 +1. Build the C++ library: + +```bash +cmake -B build . +cmake --build build +``` + +2. Copy the header and shared library: + +```bash +cp bindings/c/include/cimg2num.h /your/project/dir +cp build/libimg2num.so /your/project/dir # .dylib on macOS, .dll on Windows +``` + +## Quick Example + +```c +#include "cimg2num.h" +#include +#include + +int main() { + img2num_ImageToSvgConfig config = img2num_ImageToSvgConfig_default(); + config.kmeans.k = 16; + + // Assuming `image_data` is your RGBA buffer and width/height are known: + char* svg = img2num_image_to_svg( + image_data, width, height, &config + ); + + printf("%s\n", svg); + free(svg); // Important: free the returned SVG string + return 0; +} +``` + +## Memory Management + +- All functions that return `char*` (e.g., `img2num_image_to_svg`, `img2num_labels_to_svg`) allocate memory internally. **Callers must `free()` the result.** +- Buffers passed in (`uint8_t*`, `int32_t*`) are modified in-place or copied as specified. diff --git a/docs/docs/concepts.md b/docs/docs/concepts.md new file mode 100644 index 000000000..7d01cbaca --- /dev/null +++ b/docs/docs/concepts.md @@ -0,0 +1,58 @@ +--- +id: concepts +title: Core Concepts +sidebar_position: 4 +--- + +# Core Concepts + +Understanding these concepts will help you get the best results from Img2Num. + +## Color Spaces + +Img2Num supports two color spaces for k-means clustering: + +| Space | ID | Description | Use when… | +| :--- | :--- | :--- | :--- | +| **CIE LAB** | `0` | Perceptually uniform — distances match human color perception. | Accurate color matching matters more than speed. | +| **sRGB** | `1` | Faster computation in the native display space. | You need speed and color accuracy is secondary. | + +## Bilateral Filtering + +The bilateral filter applies two Gaussian kernels: + +- **Spatial kernel** (`sigma_spatial`): Smooths pixels close to each other in the image plane. +- **Range kernel** (`sigma_range`): Smoothes pixels with similar intensity values. + +``` +result = weighted_average(input_pixels) +weight = exp(-dist² / 2σ²_spatial) × exp(-Δintensity² / 2σ²_range) +``` + +Typical values: + +- `sigma_spatial = 3` +- `sigma_range = 50` + +## K-Means Clustering + +K-means groups pixels into *k* clusters based on color distance in the chosen color space. + +- **`k` (num_colors)**: How many colors the output should contain. +- **`max_iter`**: Stop the algorithm early if `100` iterations aren't enough. + +:::tip +Larger images benefit from more colors (`k`), but too many will produce noisy contours. +::: + +## Contour Tracing & Simplification + +Img2Num uses the following pipeline for finding vector paths: + +1. **Label image** from the k-means output. +2. **Find contours** of each label using marching-squares-style boundary detection. +3. **Simplify** contours to quadratic B-splines with area-based filtering (`min_area`). + +## Minimum Cluster Area + +`min_area` (default `100` pixels) filters out small contours that are usually noise or fine texture. Increase it for cleaner, more stylized SVGs. diff --git a/docs/docs/cpp/api-reference.md b/docs/docs/cpp/api-reference.md index 3fc2a1e03..50db873a3 100644 --- a/docs/docs/cpp/api-reference.md +++ b/docs/docs/cpp/api-reference.md @@ -1,31 +1,111 @@ --- +id: cpp-api-reference title: C++ API Reference -description: > - This page provides a full-page view of the Img2Num's C++ API reference - generated by Doxygen. Use the fullscreen button to expand the view - for easier navigation and code browsing. +sidebar_position: 1 --- -import FullscreenIframe from "@site/src/components/FullscreenIframe"; - -export const DocsLink = () => ( - { - e.preventDefault(); - window.location.href = "/Img2Num/info/docs/cpp/api/"; - }} - > - {" "} - Doxygen documentation{" "} - +# C++ API Reference + +The C++ API lives in the `img2num` namespace and is declared in `img2num.h`. + +## `image_to_svg` + +```cpp +#include + +std::string result = img2num::image_to_svg( + data, // uint8_t* — image buffer (H×W×4, RGBA) + width, // int + height, // int + config // img2num::ImageToSvgConfig +); +``` + +### ImageToSvgConfig + +| Member | Default | Description | +| :--- | :--- | :--- | +| `bilateral_filter.sigma_spatial` | 3.0 | Spatial smoothing distance | +| `bilateral_filter.sigma_range` | 50.0 | Color intensity smoothing | +| `kmeans.k` | 16 | Number of colors | +| `kmeans.max_iter` | 100 | K-means iterations | +| `min_cluster_area` | 100 | Minimum contour area (px) | +| `color_space` | 0 | 0 = CIE LAB, 1 = sRGB | + +## `gaussian_blur_fft` + +```cpp +void img2num::gaussian_blur_fft(uint8_t* image, size_t width, size_t height, double sigma); +``` + +Applies a Gaussian blur using a 2-D FFT. Modifies `image` in-place. + +## `invert_image` + +```cpp +void img2num::invert_image(uint8_t* ptr, int width, int height); +``` + +Inverts pixel values in-place. + +## `threshold_image` + +```cpp +void img2num::threshold_image(uint8_t* ptr, int width, int height, int num_thresholds); +``` + +Reduces the image to `num_thresholds` discrete intensity levels. + +## `black_threshold_image` + +```cpp +void img2num::black_threshold_image(uint8_t* ptr, int width, int height, int num_thresholds); +``` + +Like `threshold_image`, but biased toward darker output. + +## `kmeans` + +```cpp +void img2num::kmeans( + const uint8_t* data, + uint8_t* out_data, + int32_t* out_labels, + int32_t width, + int32_t height, + int32_t k, + int32_t max_iter, + uint8_t color_space +); +``` + +Fills `out_data` with clustered pixel values and `out_labels` with per-pixel cluster indices. + +## `bilateral_filter` + +```cpp +void img2num::bilateral_filter( + uint8_t* image, + size_t width, + size_t height, + double sigma_spatial, + double sigma_range, + uint8_t color_space ); +``` -> Don't like iframes? -> Visit the{' '} directly. +Edge-preserving smoothing applied in-place. - +## `labels_to_svg` -## About this page +```cpp +std::string img2num::labels_to_svg( + const uint8_t* data, + const int32_t* labels, + int width, + int height, + int min_area +); +``` -This page is a direct proxy for the{' '} { e.preventDefault(); window.location.href = "/Img2Num/info/docs/cpp/api/"; }}> Doxygen documentation generated from the C++ core directory. +Converts a labeled region map into SVG markup. diff --git a/docs/docs/cpp/docs/index.md b/docs/docs/cpp/docs/index.md index 8d1b5a357..dcbe5e6b0 100644 --- a/docs/docs/cpp/docs/index.md +++ b/docs/docs/cpp/docs/index.md @@ -1,12 +1,62 @@ -# Docs +# C++ API Documentation -import Hedgehog from "@site/src/components/Hedgehog"; +The C++ API provides a full-featured interface to Img2Num's image processing pipeline. It is declared in `img2num.h` (under `core/include`). -:::danger Help Wanted! -We need help with writing manual docs. -If you're interested, please see the [contributing guide](../../contributing) first. +## Installation - -::: +1. Build the library: -> You don't need an issue to work on this - just mention it in your PR body.🦔 +```bash +cmake -B build . +cmake --build build +``` + +2. Link against `img2num`: + +```cmake +find_package(img2num REQUIRED) +target_link_libraries(myapp PRIVATE img2num) +``` + +Or include the headers directly: + +```cpp +#include "img2num.h" +``` + +## Quick Example + +```cpp +#include +#include + +int main() { + uint8_t* image_data = /* your RGBA buffer */; + int width = 800, height = 600; + + // Convert raster to SVG + std::string svg = img2num::image_to_svg( + image_data, width, height, + img2num::ImageToSvgConfig{} + ); + + std::cout << svg << std::endl; + return 0; +} +``` + +## Pipeline Functions + +| Function | Description | +| :--- | :--- | +| `bilateral_filter` | Edge-preserving smoothing | +| `kmeans` | Color palette reduction | +| `labels_to_svg` | Contour detection & vectorization | +| `image_to_svg` | Full pipeline (filter → cluster → trace) | + +## Color Spaces + +| Space | Constant | Use | +| :--- | :--- | :--- | +| **CIE LAB** | `0` | Perceptually accurate | +| **sRGB** | `1` | Faster computation | diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md new file mode 100644 index 000000000..d068ef66a --- /dev/null +++ b/docs/docs/getting-started.md @@ -0,0 +1,87 @@ +--- +id: getting-started +title: Getting Started +sidebar_position: 3 +--- + +# Getting Started + +This guide walks you through your first Img2Num conversion in under 5 minutes. + +## Prerequisites + +- A raster image (PNG, JPG, BMP, etc.) +- Node.js 14+ or a modern browser with ES module support + +## Step 1 — Install the package + +```bash +npm install img2num +``` + +## Step 2 — Convert an image to SVG + +```js +import { + imageToUint8ClampedArray, + bilateralFilter, + kmeans, + findContours +} from "img2num"; + +// Load your image +const imageFile = /* File object from or fs.readFile */; +const { pixels, width, height } = await imageToUint8ClampedArray(imageFile); + +// Optional: denoise with bilateral filter +const filtered = await bilateralFilter({ pixels, width, height }); + +// Reduce palette to 16 colors +const { labels } = await kmeans({ + pixels: filtered, + width, + height, + num_colors: 16, +}); + +// Convert to SVG +const { svg } = await findContours({ + pixels: filtered, + labels, + width, + height, +}); + +// Use the SVG string +console.log(svg); +``` + +## Quick-start: One-liner with `imageToSvg` + +Img2Num also provides a convenience wrapper that chains filtering, clustering, and contour detection: + +```js +import { imageToSvg } from "img2num"; + +const { svg } = await imageToSvg({ pixels, width, height }); +``` + +## What happens under the hood? + +```mermaid +flowchart LR + A[Raster Image] --> B[Bilateral Filter] + B --> C[K-Means Clustering] + C --> D[Contour Tracing] + D --> E[SVG Output] +``` + +1. **Bilateral Filter** — smooths noise while preserving edges. +2. **K-Means Clustering** — reduces the palette to a configurable color count. +3. **Contour Tracing** — detects region boundaries and fits them to quadratic B-splines. + +## Next steps + +- [Concepts](./concepts) — learn about color spaces, filtering, and contours. +- [API Reference](./api-reference) — full parameter documentation. +- [Performance](./performance) — tips for speeding up your pipeline. diff --git a/docs/docs/index.md b/docs/docs/index.md index 16c3ae46e..e7b064183 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -6,15 +6,32 @@ sidebar_position: 1 # Welcome to Img2Num! 🦔 -Img2Num is a lightweight, high-performance library for converting raster images to to SVGs with ease and speed. +Img2Num is a lightweight, high-performance library for converting raster images to SVGs with ease and speed. -Whether you're a beginner or an advanced user, you'll find everything you need here to get started and master Img2Num. +## Quick Overview -## Getting Started +- **Convert raster images to SVG** — PNG, JPG, BMP → scalable vector paths +- **Multi-platform** — C++, C, Python, and JavaScript (WASM) +- **High performance** — WASM-powered, runs in browsers and Node.js +- **Highly configurable** — bilateral filtering, k-means clustering, contour tracing -Follow the relevant installation guide from the following: +## Getting Started -- [JavaScript](./js) +1. **[Installation](./installation)** — Install Img2Num for your platform. +2. **[Getting Started](./getting-started)** — Your first conversion in under 5 minutes. +3. **[Concepts](./concepts)** — Learn about color spaces, filtering, and contours. +4. **[API Reference](./api-reference)** — Full documentation for all bindings. +5. **[Performance](./performance)** — Tips for speeding up your pipeline. +6. **[Troubleshooting](./troubleshooting)** — Common issues and fixes. + +## API Bindings + +| Binding | Status | Docs | +| :--- | :--- | :--- | +| **JavaScript (WASM)** | ✅ Production | [JS API Reference](./js/api-reference) | +| **C++** | ✅ Production | [C++ API Reference](./cpp/api-reference) | +| **C** | ✅ Production | [C API Reference](./c/api-reference) | +| **Python** | 🟡 Early | [Python API Reference](./python/api-reference) | ## Changelog diff --git a/docs/docs/installation.md b/docs/docs/installation.md new file mode 100644 index 000000000..72d704db3 --- /dev/null +++ b/docs/docs/installation.md @@ -0,0 +1,89 @@ +--- +id: installation +title: Installation +sidebar_position: 2 +--- + +# Installation + +Img2Num provides multiple bindings. Install the one that matches your target platform. + +## JavaScript / Node.js (WASM) + +### Using a package manager + +```bash +npm install img2num +# or +pnpm add img2num +# or +yarn add img2num +``` + +### Requirements + +- Node ≥ 14 (for ESM support) +- Node ≥ 16 recommended (top-level `await`, best WASM performance) +- For browser use: modern browser with ES module and WebAssembly support + +:::tip CDN +You can also load Img2Num directly from jsDelivr: + +```html + +``` +::: + +## C++ + +### From Source + +```bash +git clone https://github.com/Ryan-Millard/Img2Num.git +cd Img2Num +mkdir build && cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make -j$(nproc) +``` + +**Required:** + +- CMake ≥ 3.16 +- C++17 compiler (GCC 7+, Clang 5+, MSVC 2017+) + +## C + +### From Source + +The C bindings are included in the C++ build. After building the C++ library, the C header is available at: + +``` +bindings/c/include/cimg2num.h +``` + +Copy `cimg2num.h` and the compiled `.so`/`.dylib`/`.dll` to your project. + +## Python + +:::warning +Python bindings are not yet available on PyPI. Build from source using the project's build scripts. +::: + +## WASM Bundler Notes + +When using a bundler (Webpack, Vite, Rollup), ensure that: + +- `.wasm` files (e.g., `build-wasm/index.wasm`) are properly served or imported. +- No external JS dependencies are required — the package is pure JS + WASM. + +## Verification + +After installation, verify the library works by importing it: + +```js +import { imageToSvg, bilateralFilter, kmeans, findContours } from "img2num"; +// Should resolve without errors +``` diff --git a/docs/docs/js/api-reference.md b/docs/docs/js/api-reference.md new file mode 100644 index 000000000..06d6229ca --- /dev/null +++ b/docs/docs/js/api-reference.md @@ -0,0 +1,76 @@ +--- +id: js-api-reference +title: JavaScript API Reference +sidebar_position: 1 +--- + +# JavaScript API Reference + +All functions are exported from the `img2num` package. They are async because they communicate with a WASM Web Worker. + +## `imageToSvg({ pixels, width, height, options })` + +One-shot raster → SVG conversion. + +| Option | Default | Description | +| :--- | :--- | :--- | +| `sigma_spatial` | `3` | Bilateral spatial sigma | +| `sigma_range` | `50` | Bilateral range sigma | +| `num_colors` | `16` | K-means cluster count | +| `max_iter` | `100` | K-means max iterations | +| `min_area` | `100` | Minimum contour area | +| `color_space` | `0` | `0` = CIE LAB, `1` = sRGB | + +**Returns:** `{ svg: string }` + +```js +import { imageToSvg } from "img2num"; +const { svg } = await imageToSvg({ pixels, width, height }); +``` + +## `bilateralFilter({ pixels, width, height, sigma_spatial, sigma_range, color_space })` + +Edge-preserving bilateral smoothing. + +**Returns:** `Promise` + +## `kmeans({ pixels, width, height, num_colors, max_iter, color_space })` + +K-means color clustering. + +**Returns:** `{ pixels: Uint8ClampedArray, labels: Int32Array }` + +## `findContours({ pixels, labels, width, height, min_area })` + +Convert labeled regions to SVG paths. + +**Returns:** `{ svg: string }` + +## `imageToUint8ClampedArray(file)` + +Loads a `File` or `Blob` into a `[pixels: Uint8ClampedArray, width: number, height: number]` tuple. + +**Returns:** `{ pixels: Uint8ClampedArray, width: number, height: number }` + +## `imageToUint8ClampedArray.fromDataUrl(dataUrl)` + +Loads an image from a Data URL. + +**Returns:** `{ pixels: Uint8ClampedArray, width: number, height: number }` + +## `callWasm({ funcName, args, bufferKeys, returnType })` + +Advanced low-level API for calling raw WASM functions. + +| Parameter | Description | +| :--- | :--- | +| `funcName` | WASM export name | +| `args` | Named arguments passed as object | +| `bufferKeys` | Array of `{ key, type }` for buffer transfers | +| `returnType` | Expected return type (`void`, `string`, etc.) | + +**Returns:** `Promise<{ output: any, returnValue: any }>` + +## `initWasmWorker()` + +Manually initializes the WASM worker. Automatically called by higher-level wrappers, but useful if you want lazy initialization. diff --git a/docs/docs/js/docs/index.md b/docs/docs/js/docs/index.md index 8d1b5a357..c85005158 100644 --- a/docs/docs/js/docs/index.md +++ b/docs/docs/js/docs/index.md @@ -1,12 +1,66 @@ -# Docs +# JavaScript Binding Documentation -import Hedgehog from "@site/src/components/Hedgehog"; +The JavaScript binding wraps Img2Num's WASM core in a clean, async API. It runs in browsers and Node.js. -:::danger Help Wanted! -We need help with writing manual docs. -If you're interested, please see the [contributing guide](../../contributing) first. +## Architecture - -::: +``` +Browser / Node.js + │ + ▼ +┌─────────────────────────┐ +│ safeWasmWrappers.js │ ← Public API (imageToSvg, kmeans, etc.) +└─────────────────────────┘ + │ + ▼ +┌─────────────────────────┐ +│ wasmClient.js │ ← Worker communication (postMessage) +└─────────────────────────┘ + │ + ▼ +┌─────────────────────────┐ +│ wasmWorker.js │ ← WASM module loader & message handler +└─────────────────────────┘ + │ + ▼ +┌─────────────────────────┐ +│ img2num_core.wasm │ ← Emscripten-compiled core (C++ → WASM) +└─────────────────────────┘ +``` -> You don't need an issue to work on this - just mention it in your PR body.🦔 +Key files: + +| File | Purpose | +| :--- | :--- | +| `safeWasmWrappers.js` | Public API — imageToSvg, bilateralFilter, kmeans, etc. | +| `wasmClient.js` | Worker communication layer | +| `wasmWorker.js` | WASM module loader, typed array handling, memory management | +| `index.js` | Package exports | + +## WASM Memory Handling + +The worker passes typed arrays between JavaScript and WASM memory via: + +1. **Allocation** — `_malloc` in WASM for the buffer size. +2. **Copy** — `HEAPU8.set()` / `HEAP32.set()` depending on array type. +3. **Call** — Pass pointers to WASM function via `ccall`. +4. **Read back** — `HEAPU8.slice()` / `HEAP32.slice()` on return. +5. **Free** — `_free(ptr)` to avoid leaks. + +## Worker Lifecycle + +- The WASM worker is initialized on first API call (lazy loading). +- A single worker instance handles all subsequent calls. +- No external dependencies — pure JS + WASM. + +## Error Handling + +Errors are caught and re-thrown as: + +```js +try { + await imageToSvg({ pixels, width, height }); +} catch (err) { + console.error(err.message); // e.g. "Missing funcName", "Unsupported type" +} +``` diff --git a/docs/docs/performance.md b/docs/docs/performance.md new file mode 100644 index 000000000..7f09dc7a7 --- /dev/null +++ b/docs/docs/performance.md @@ -0,0 +1,50 @@ +--- +id: performance +title: Performance +sidebar_position: 5 +--- + +# Performance Tips + +Img2Num runs inside WASM on a Web Worker. Here are tips to maximize throughput. + +## Parallel Processing + +Each function call spawns a message to the worker. For batch processing, process images in parallel: + +```js +const results = await Promise.all(images.map(img => imageToSvg(img))); +``` + +## Tune Parameters + +| Parameter | Tuning Direction | Effect | +| :--- | :--- | :--- | +| `sigma_spatial` | Lower → faster | Less spatial smoothing | +| `num_colors` | Lower → faster | Fewer clusters | +| `max_iter` | Lower → faster | Fewer k-means iterations | +| `min_area` | Higher → faster | Fewer contours to trace | + +## Downscale Large Images + +Processing at full resolution can be slow. Scale down to 1080p or 720p before conversion: + +```js +const canvas = document.createElement("canvas"); +canvas.width = 720; +canvas.height = 720; +const ctx = canvas.getContext("2d"); +ctx.drawImage(image, 0, 0, 720, 720); +const { pixels, width, height } = ctx.getImageData(0, 0, 720, 720); +``` + +## Worker Lifecycle + +If you call Img2Num repeatedly in a single page, keep the worker alive. Img2Num initializes the worker once and reuses it automatically. + +## Node.js Performance + +In Node.js, the worker is process-isolated. For server-side rendering, consider: + +- Using a worker pool +- Reusing the same process across multiple requests diff --git a/docs/docs/python/api-reference.md b/docs/docs/python/api-reference.md new file mode 100644 index 000000000..7e5f26c2f --- /dev/null +++ b/docs/docs/python/api-reference.md @@ -0,0 +1,73 @@ +--- +id: python-api-reference +title: Python API Reference +sidebar_position: 1 +--- + +# Python API Reference + +All functions are exposed via the `img2num` Python package. They accept NumPy arrays and automatically inject `width`/`height` from the array shape. + +## `image_to_svg(image, *, width, height, config=None)` + +Convert a raster image buffer into an SVG string. + +**Parameters:** + +| Name | Type | Description | +| :--- | :--- | :--- | +| `image` | `NDArray[np.uint8]` | Input image (H, W, C). | +| `width` | `int` | Image width (injected automatically from array shape). | +| `height` | `int` | Image height (injected automatically from array shape). | +| `config` | `ImageToSvgConfig` | Optional override of defaults. | + +**Returns:** `str` — SVG markup. + +```python +from img2num import image_to_svg + +svg = image_to_svg(image, width=800, height=600) +``` + +## `bilateral_filter(image, sigma_spatial, sigma_range, color_space, *, width, height)` + +Edge-preserving smoothing. + +**Parameters:** + +| Name | Type | Default | +| :--- | :--- | :--- | +| `image` | `NDArray[np.uint8]` | — | +| `sigma_spatial` | `float` | — | +| `sigma_range` | `float` | — | +| `color_space` | `int` | — | + +**Returns:** `NDArray[np.uint8]` — Filtered image. + +## `kmeans(data, k, max_iter, color_space, *, width, height)` + +K-means color clustering. + +**Parameters:** + +| Name | Type | Default | +| :--- | :--- | :--- | +| `data` | `NDArray[np.uint8]` | — | +| `k` | `int` | — | +| `max_iter` | `int` | — | +| `color_space` | `int` | — | + +**Returns:** `(NDArray[np.uint8], NDArray[np.int])` — `(clustered_data, labels)` + +## `findContours(labels, min_area=100, *, width, height)` + +Convert label map to vector paths. + +**Parameters:** + +| Name | Type | Default | +| :--- | :--- | :--- | +| `labels` | `NDArray[np.int]` | — | +| `min_area` | `int` | 100 | + +**Returns:** `str` — SVG markup. diff --git a/docs/docs/python/index.md b/docs/docs/python/index.md new file mode 100644 index 000000000..fe3e79b8c --- /dev/null +++ b/docs/docs/python/index.md @@ -0,0 +1,55 @@ +--- +title: Img2Num Python +sidebar_label: Python +sidebar_position: 5 +--- + +# Python Binding + +The Python binding provides NumPy-backed wrappers around the Img2Num core library. + +## Requirements + +- Python ≥ 3.7 +- NumPy +- WASM runtime (automatically installed with the package) + +## Installation + +```bash +pip install img2num +``` + +## Usage + +```python +import numpy as np +from img2num import image_to_svg + +# Assuming `image` is a NumPy array of shape (H, W, C) +svg = image_to_svg(image, width=800, height=600) +print(svg) +``` + +## Available Functions + +| Function | Description | +| :--- | :--- | +| `image_to_svg` | Full raster → SVG pipeline | +| `bilateral_filter` | Edge-preserving smoothing | +| `kmeans` | Color clustering | +| `findContours` | Contour detection | + +## Configuration + +Override defaults by passing an `ImageToSvgConfig` object: + +```python +from img2num import ImageToSvgConfig + +config = ImageToSvgConfig() +config.kmeans.k = 32 # More colors +config.min_cluster_area = 50 # Less filtering + +svg = image_to_svg(image, width=800, height=600, config=config) +``` diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md new file mode 100644 index 000000000..bf76d890f --- /dev/null +++ b/docs/docs/troubleshooting.md @@ -0,0 +1,55 @@ +--- +id: troubleshooting +title: Troubleshooting +sidebar_position: 5 +--- + +# Troubleshooting + +Common issues and their solutions. + +## WASM Loading Fails in Node.js + +**Symptom:** `Error: Could not load WASM module` or similar. + +**Cause:** The `.wasm` binary is not found relative to `index.js`. + +**Fix:** Ensure `build-wasm/index.wasm` is present alongside `index.js` in the installed package: + +```bash +ls node_modules/img2num/build-wasm/ +``` + +If missing, reinstall: + +```bash +npm uninstall img2num +npm install img2num +``` + +## Blurry or Over-Smoothed Output + +Increase `sigma_spatial` or decrease it depending on the image. If it's over-smoothed, reduce it. + +## Jagged / Noisy SVG Paths + +Increase `min_area` to filter out tiny contours, or increase `sigma_spatial` to smooth noise before clustering. + +## K-Means Runs Slow in the Browser + +K-means can take seconds on large images. Try: + +- Lowering `num_colors` +- Lowering `max_iter` +- Using a smaller source image for development + +## Memory Errors (OOM) + +The WASM heap is fixed at compile time. Very large images may exceed it. Consider: + +- Downscaling the input image +- Splitting the image into tiles + +## Missing CIE LAB Output + +Make sure `color_space = 0` (default). `color_space = 1` uses sRGB which may produce different cluster boundaries. From be56d58b8aabd3c4060cfc51bc29eab3be005b91 Mon Sep 17 00:00:00 2001 From: Krasner Date: Wed, 20 May 2026 20:45:58 +0000 Subject: [PATCH 02/11] formatting --- docs/docs/api-reference.md | 28 ++++++++++---------- docs/docs/concepts.md | 8 +++--- docs/docs/cpp/api-reference.md | 16 +++++------ docs/docs/cpp/docs/index.md | 20 +++++++------- docs/docs/index.md | 12 ++++----- docs/docs/installation.md | 4 +-- docs/docs/js/api-reference.md | 24 ++++++++--------- docs/docs/js/docs/index.md | 12 ++++----- docs/docs/performance.md | 14 +++++----- docs/docs/python/api-reference.md | 44 +++++++++++++++---------------- docs/docs/python/index.md | 12 ++++----- 11 files changed, 97 insertions(+), 97 deletions(-) diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md index e02aa2fb1..9f1d7f320 100644 --- a/docs/docs/api-reference.md +++ b/docs/docs/api-reference.md @@ -8,12 +8,12 @@ sidebar_position: 6 Img2Num provides bindings for multiple languages. Choose the one that fits your workflow: -| Language | Docs | -| :--- | :--- | -| **JavaScript** | [JS API Reference](./js/api-reference) | -| **C++** | [C++ API Reference](./cpp/api-reference) | -| **C** | [C API Reference](./c/api-reference) | -| **Python** | [Python API Reference](./python/api-reference) | +| Language | Docs | +| :------------- | :--------------------------------------------- | +| **JavaScript** | [JS API Reference](./js/api-reference) | +| **C++** | [C++ API Reference](./cpp/api-reference) | +| **C** | [C API Reference](./c/api-reference) | +| **Python** | [Python API Reference](./python/api-reference) | ## Common Concepts Across All Bindings @@ -26,14 +26,14 @@ All APIs share these core concepts: ## Shared Parameters -| Parameter | Type | Default | Description | -| :--- | :--- | :--- | :--- | -| `sigma_spatial` | `float` | `3` | Bilateral spatial sigma | -| `sigma_range` | `float` | `50` | Bilateral range sigma | -| `num_colors` / `k` | `int` | `16` | Number of clusters | -| `max_iter` | `int` | `100` | K-means iterations | -| `min_area` | `int` | `100` | Minimum contour area | -| `color_space` | `int` | `0` | `0` = CIE LAB, `1` = sRGB | +| Parameter | Type | Default | Description | +| :----------------- | :------ | :------ | :------------------------ | +| `sigma_spatial` | `float` | `3` | Bilateral spatial sigma | +| `sigma_range` | `float` | `50` | Bilateral range sigma | +| `num_colors` / `k` | `int` | `16` | Number of clusters | +| `max_iter` | `int` | `100` | K-means iterations | +| `min_area` | `int` | `100` | Minimum contour area | +| `color_space` | `int` | `0` | `0` = CIE LAB, `1` = sRGB | ## Pipeline Flow diff --git a/docs/docs/concepts.md b/docs/docs/concepts.md index 7d01cbaca..2d5a89aa4 100644 --- a/docs/docs/concepts.md +++ b/docs/docs/concepts.md @@ -12,10 +12,10 @@ Understanding these concepts will help you get the best results from Img2Num. Img2Num supports two color spaces for k-means clustering: -| Space | ID | Description | Use when… | -| :--- | :--- | :--- | :--- | +| Space | ID | Description | Use when… | +| :---------- | :-- | :------------------------------------------------------------- | :----------------------------------------------- | | **CIE LAB** | `0` | Perceptually uniform — distances match human color perception. | Accurate color matching matters more than speed. | -| **sRGB** | `1` | Faster computation in the native display space. | You need speed and color accuracy is secondary. | +| **sRGB** | `1` | Faster computation in the native display space. | You need speed and color accuracy is secondary. | ## Bilateral Filtering @@ -36,7 +36,7 @@ Typical values: ## K-Means Clustering -K-means groups pixels into *k* clusters based on color distance in the chosen color space. +K-means groups pixels into _k_ clusters based on color distance in the chosen color space. - **`k` (num_colors)**: How many colors the output should contain. - **`max_iter`**: Stop the algorithm early if `100` iterations aren't enough. diff --git a/docs/docs/cpp/api-reference.md b/docs/docs/cpp/api-reference.md index 50db873a3..314d1c9c6 100644 --- a/docs/docs/cpp/api-reference.md +++ b/docs/docs/cpp/api-reference.md @@ -23,14 +23,14 @@ std::string result = img2num::image_to_svg( ### ImageToSvgConfig -| Member | Default | Description | -| :--- | :--- | :--- | -| `bilateral_filter.sigma_spatial` | 3.0 | Spatial smoothing distance | -| `bilateral_filter.sigma_range` | 50.0 | Color intensity smoothing | -| `kmeans.k` | 16 | Number of colors | -| `kmeans.max_iter` | 100 | K-means iterations | -| `min_cluster_area` | 100 | Minimum contour area (px) | -| `color_space` | 0 | 0 = CIE LAB, 1 = sRGB | +| Member | Default | Description | +| :------------------------------- | :------ | :------------------------- | +| `bilateral_filter.sigma_spatial` | 3.0 | Spatial smoothing distance | +| `bilateral_filter.sigma_range` | 50.0 | Color intensity smoothing | +| `kmeans.k` | 16 | Number of colors | +| `kmeans.max_iter` | 100 | K-means iterations | +| `min_cluster_area` | 100 | Minimum contour area (px) | +| `color_space` | 0 | 0 = CIE LAB, 1 = sRGB | ## `gaussian_blur_fft` diff --git a/docs/docs/cpp/docs/index.md b/docs/docs/cpp/docs/index.md index dcbe5e6b0..f65f78d70 100644 --- a/docs/docs/cpp/docs/index.md +++ b/docs/docs/cpp/docs/index.md @@ -47,16 +47,16 @@ int main() { ## Pipeline Functions -| Function | Description | -| :--- | :--- | -| `bilateral_filter` | Edge-preserving smoothing | -| `kmeans` | Color palette reduction | -| `labels_to_svg` | Contour detection & vectorization | -| `image_to_svg` | Full pipeline (filter → cluster → trace) | +| Function | Description | +| :----------------- | :--------------------------------------- | +| `bilateral_filter` | Edge-preserving smoothing | +| `kmeans` | Color palette reduction | +| `labels_to_svg` | Contour detection & vectorization | +| `image_to_svg` | Full pipeline (filter → cluster → trace) | ## Color Spaces -| Space | Constant | Use | -| :--- | :--- | :--- | -| **CIE LAB** | `0` | Perceptually accurate | -| **sRGB** | `1` | Faster computation | +| Space | Constant | Use | +| :---------- | :------- | :-------------------- | +| **CIE LAB** | `0` | Perceptually accurate | +| **sRGB** | `1` | Faster computation | diff --git a/docs/docs/index.md b/docs/docs/index.md index e7b064183..bd5bc6ce9 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -26,12 +26,12 @@ Img2Num is a lightweight, high-performance library for converting raster images ## API Bindings -| Binding | Status | Docs | -| :--- | :--- | :--- | -| **JavaScript (WASM)** | ✅ Production | [JS API Reference](./js/api-reference) | -| **C++** | ✅ Production | [C++ API Reference](./cpp/api-reference) | -| **C** | ✅ Production | [C API Reference](./c/api-reference) | -| **Python** | 🟡 Early | [Python API Reference](./python/api-reference) | +| Binding | Status | Docs | +| :-------------------- | :------------ | :--------------------------------------------- | +| **JavaScript (WASM)** | ✅ Production | [JS API Reference](./js/api-reference) | +| **C++** | ✅ Production | [C++ API Reference](./cpp/api-reference) | +| **C** | ✅ Production | [C API Reference](./c/api-reference) | +| **Python** | 🟡 Early | [Python API Reference](./python/api-reference) | ## Changelog diff --git a/docs/docs/installation.md b/docs/docs/installation.md index 72d704db3..a9bc09542 100644 --- a/docs/docs/installation.md +++ b/docs/docs/installation.md @@ -31,10 +31,10 @@ You can also load Img2Num directly from jsDelivr: ```html ``` + ::: ## C++ diff --git a/docs/docs/js/api-reference.md b/docs/docs/js/api-reference.md index 06d6229ca..14d2226dd 100644 --- a/docs/docs/js/api-reference.md +++ b/docs/docs/js/api-reference.md @@ -12,14 +12,14 @@ All functions are exported from the `img2num` package. They are async because th One-shot raster → SVG conversion. -| Option | Default | Description | -| :--- | :--- | :--- | -| `sigma_spatial` | `3` | Bilateral spatial sigma | -| `sigma_range` | `50` | Bilateral range sigma | -| `num_colors` | `16` | K-means cluster count | -| `max_iter` | `100` | K-means max iterations | -| `min_area` | `100` | Minimum contour area | -| `color_space` | `0` | `0` = CIE LAB, `1` = sRGB | +| Option | Default | Description | +| :-------------- | :------ | :------------------------ | +| `sigma_spatial` | `3` | Bilateral spatial sigma | +| `sigma_range` | `50` | Bilateral range sigma | +| `num_colors` | `16` | K-means cluster count | +| `max_iter` | `100` | K-means max iterations | +| `min_area` | `100` | Minimum contour area | +| `color_space` | `0` | `0` = CIE LAB, `1` = sRGB | **Returns:** `{ svg: string }` @@ -62,10 +62,10 @@ Loads an image from a Data URL. Advanced low-level API for calling raw WASM functions. -| Parameter | Description | -| :--- | :--- | -| `funcName` | WASM export name | -| `args` | Named arguments passed as object | +| Parameter | Description | +| :----------- | :-------------------------------------------- | +| `funcName` | WASM export name | +| `args` | Named arguments passed as object | | `bufferKeys` | Array of `{ key, type }` for buffer transfers | | `returnType` | Expected return type (`void`, `string`, etc.) | diff --git a/docs/docs/js/docs/index.md b/docs/docs/js/docs/index.md index c85005158..6df95c8c1 100644 --- a/docs/docs/js/docs/index.md +++ b/docs/docs/js/docs/index.md @@ -30,12 +30,12 @@ Browser / Node.js Key files: -| File | Purpose | -| :--- | :--- | -| `safeWasmWrappers.js` | Public API — imageToSvg, bilateralFilter, kmeans, etc. | -| `wasmClient.js` | Worker communication layer | -| `wasmWorker.js` | WASM module loader, typed array handling, memory management | -| `index.js` | Package exports | +| File | Purpose | +| :-------------------- | :---------------------------------------------------------- | +| `safeWasmWrappers.js` | Public API — imageToSvg, bilateralFilter, kmeans, etc. | +| `wasmClient.js` | Worker communication layer | +| `wasmWorker.js` | WASM module loader, typed array handling, memory management | +| `index.js` | Package exports | ## WASM Memory Handling diff --git a/docs/docs/performance.md b/docs/docs/performance.md index 7f09dc7a7..974ead3b3 100644 --- a/docs/docs/performance.md +++ b/docs/docs/performance.md @@ -13,17 +13,17 @@ Img2Num runs inside WASM on a Web Worker. Here are tips to maximize throughput. Each function call spawns a message to the worker. For batch processing, process images in parallel: ```js -const results = await Promise.all(images.map(img => imageToSvg(img))); +const results = await Promise.all(images.map((img) => imageToSvg(img))); ``` ## Tune Parameters -| Parameter | Tuning Direction | Effect | -| :--- | :--- | :--- | -| `sigma_spatial` | Lower → faster | Less spatial smoothing | -| `num_colors` | Lower → faster | Fewer clusters | -| `max_iter` | Lower → faster | Fewer k-means iterations | -| `min_area` | Higher → faster | Fewer contours to trace | +| Parameter | Tuning Direction | Effect | +| :-------------- | :--------------- | :----------------------- | +| `sigma_spatial` | Lower → faster | Less spatial smoothing | +| `num_colors` | Lower → faster | Fewer clusters | +| `max_iter` | Lower → faster | Fewer k-means iterations | +| `min_area` | Higher → faster | Fewer contours to trace | ## Downscale Large Images diff --git a/docs/docs/python/api-reference.md b/docs/docs/python/api-reference.md index 7e5f26c2f..aa4f6840d 100644 --- a/docs/docs/python/api-reference.md +++ b/docs/docs/python/api-reference.md @@ -14,12 +14,12 @@ Convert a raster image buffer into an SVG string. **Parameters:** -| Name | Type | Description | -| :--- | :--- | :--- | -| `image` | `NDArray[np.uint8]` | Input image (H, W, C). | -| `width` | `int` | Image width (injected automatically from array shape). | -| `height` | `int` | Image height (injected automatically from array shape). | -| `config` | `ImageToSvgConfig` | Optional override of defaults. | +| Name | Type | Description | +| :------- | :------------------ | :------------------------------------------------------ | +| `image` | `NDArray[np.uint8]` | Input image (H, W, C). | +| `width` | `int` | Image width (injected automatically from array shape). | +| `height` | `int` | Image height (injected automatically from array shape). | +| `config` | `ImageToSvgConfig` | Optional override of defaults. | **Returns:** `str` — SVG markup. @@ -35,12 +35,12 @@ Edge-preserving smoothing. **Parameters:** -| Name | Type | Default | -| :--- | :--- | :--- | -| `image` | `NDArray[np.uint8]` | — | -| `sigma_spatial` | `float` | — | -| `sigma_range` | `float` | — | -| `color_space` | `int` | — | +| Name | Type | Default | +| :-------------- | :------------------ | :------ | +| `image` | `NDArray[np.uint8]` | — | +| `sigma_spatial` | `float` | — | +| `sigma_range` | `float` | — | +| `color_space` | `int` | — | **Returns:** `NDArray[np.uint8]` — Filtered image. @@ -50,12 +50,12 @@ K-means color clustering. **Parameters:** -| Name | Type | Default | -| :--- | :--- | :--- | -| `data` | `NDArray[np.uint8]` | — | -| `k` | `int` | — | -| `max_iter` | `int` | — | -| `color_space` | `int` | — | +| Name | Type | Default | +| :------------ | :------------------ | :------ | +| `data` | `NDArray[np.uint8]` | — | +| `k` | `int` | — | +| `max_iter` | `int` | — | +| `color_space` | `int` | — | **Returns:** `(NDArray[np.uint8], NDArray[np.int])` — `(clustered_data, labels)` @@ -65,9 +65,9 @@ Convert label map to vector paths. **Parameters:** -| Name | Type | Default | -| :--- | :--- | :--- | -| `labels` | `NDArray[np.int]` | — | -| `min_area` | `int` | 100 | +| Name | Type | Default | +| :--------- | :---------------- | :------ | +| `labels` | `NDArray[np.int]` | — | +| `min_area` | `int` | 100 | **Returns:** `str` — SVG markup. diff --git a/docs/docs/python/index.md b/docs/docs/python/index.md index fe3e79b8c..3a099e914 100644 --- a/docs/docs/python/index.md +++ b/docs/docs/python/index.md @@ -33,12 +33,12 @@ print(svg) ## Available Functions -| Function | Description | -| :--- | :--- | -| `image_to_svg` | Full raster → SVG pipeline | -| `bilateral_filter` | Edge-preserving smoothing | -| `kmeans` | Color clustering | -| `findContours` | Contour detection | +| Function | Description | +| :----------------- | :------------------------- | +| `image_to_svg` | Full raster → SVG pipeline | +| `bilateral_filter` | Edge-preserving smoothing | +| `kmeans` | Color clustering | +| `findContours` | Contour detection | ## Configuration From 945cade3a01002aad620edce54a0d370497e9894 Mon Sep 17 00:00:00 2001 From: Krasner Date: Thu, 21 May 2026 02:40:13 +0000 Subject: [PATCH 03/11] updated links --- docs/docs/api-reference.md | 8 ++++---- docs/docs/contributing/index.md | 4 ++-- docs/docs/getting-started.md | 6 +++--- docs/docs/index.md | 22 +++++++++++----------- docs/docs/internal/index.md | 12 ++++++------ docs/docs/js/index.md | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md index 9f1d7f320..a185a1238 100644 --- a/docs/docs/api-reference.md +++ b/docs/docs/api-reference.md @@ -10,10 +10,10 @@ Img2Num provides bindings for multiple languages. Choose the one that fits your | Language | Docs | | :------------- | :--------------------------------------------- | -| **JavaScript** | [JS API Reference](./js/api-reference) | -| **C++** | [C++ API Reference](./cpp/api-reference) | -| **C** | [C API Reference](./c/api-reference) | -| **Python** | [Python API Reference](./python/api-reference) | +| **JavaScript** | [JS API Reference](/docs/js/api-reference) | +| **C++** | [C++ API Reference](/docs/cpp/api-reference) | +| **C** | [C API Reference](/docs/c/api-reference) | +| **Python** | [Python API Reference](/docs/python/api-reference) | ## Common Concepts Across All Bindings diff --git a/docs/docs/contributing/index.md b/docs/docs/contributing/index.md index 5098ac0f1..109df1572 100644 --- a/docs/docs/contributing/index.md +++ b/docs/docs/contributing/index.md @@ -10,7 +10,7 @@ First off, thank you for considering contributing to Img2Num! We welcome any kin ## Code of Conduct -Please review and adhere to our [Code of Conduct](./code-of-conduct.md) to help foster an open and welcoming environment. +Please review and adhere to our [Code of Conduct](/docs/code-of-conduct.md) to help foster an open and welcoming environment. ## Reporting Issues @@ -50,6 +50,6 @@ When a claim expires: ## Development Setup -The [Setup & Dependencies](./setup-and-dependencies) section shows how to clone and run the application for the first time. +The [Setup & Dependencies](/docs/setup-and-dependencies) section shows how to clone and run the application for the first time. The [scripts](../internal/scripts) section shows all of the available scripts you may find useful whilst working on Img2Num's source code as well as a helpful way to find specific scripts if you have forgotten one. diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index d068ef66a..0f5c1eafe 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -82,6 +82,6 @@ flowchart LR ## Next steps -- [Concepts](./concepts) — learn about color spaces, filtering, and contours. -- [API Reference](./api-reference) — full parameter documentation. -- [Performance](./performance) — tips for speeding up your pipeline. +- [Concepts](/docs/concepts) — learn about color spaces, filtering, and contours. +- [API Reference](/docs/api-reference) — full parameter documentation. +- [Performance](/docs/performance) — tips for speeding up your pipeline. diff --git a/docs/docs/index.md b/docs/docs/index.md index bd5bc6ce9..b363a6f7d 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -17,21 +17,21 @@ Img2Num is a lightweight, high-performance library for converting raster images ## Getting Started -1. **[Installation](./installation)** — Install Img2Num for your platform. -2. **[Getting Started](./getting-started)** — Your first conversion in under 5 minutes. -3. **[Concepts](./concepts)** — Learn about color spaces, filtering, and contours. -4. **[API Reference](./api-reference)** — Full documentation for all bindings. -5. **[Performance](./performance)** — Tips for speeding up your pipeline. -6. **[Troubleshooting](./troubleshooting)** — Common issues and fixes. +1. **[Installation](/docs/installation)** — Install Img2Num for your platform. +2. **[Getting Started](/docs/getting-started)** — Your first conversion in under 5 minutes. +3. **[Concepts](/docs/concepts)** — Learn about color spaces, filtering, and contours. +4. **[API Reference](/docs/api-reference)** — Full documentation for all bindings. +5. **[Performance](/docs/performance)** — Tips for speeding up your pipeline. +6. **[Troubleshooting](/docs/troubleshooting)** — Common issues and fixes. ## API Bindings | Binding | Status | Docs | | :-------------------- | :------------ | :--------------------------------------------- | -| **JavaScript (WASM)** | ✅ Production | [JS API Reference](./js/api-reference) | -| **C++** | ✅ Production | [C++ API Reference](./cpp/api-reference) | -| **C** | ✅ Production | [C API Reference](./c/api-reference) | -| **Python** | 🟡 Early | [Python API Reference](./python/api-reference) | +| **JavaScript (WASM)** | ✅ Production | [JS API Reference](/docs/js/api-reference) | +| **C++** | ✅ Production | [C++ API Reference](/docs/cpp/api-reference) | +| **C** | ✅ Production | [C API Reference](/docs/c/api-reference) | +| **Python** | 🟡 Early | [Python API Reference](/docs/python/api-reference) | ## Changelog @@ -40,7 +40,7 @@ Our [changelog](/changelog) is quite empty right now since we haven't had our fi --- We hope you enjoy using **Img2Num**! -For issues or contributions, see our [contributors guide](./contributing) or visit our +For issues or contributions, see our [contributors guide](/docs/contributing) or visit our [GitHub repository](https://github.com/Ryan-Millard/Img2Num/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22). :::note diff --git a/docs/docs/internal/index.md b/docs/docs/internal/index.md index a7b9fff46..719f145cb 100644 --- a/docs/docs/internal/index.md +++ b/docs/docs/internal/index.md @@ -29,13 +29,13 @@ This documentation serves three main goals: ## What You Will Find Here -- [Core docs](./core) -- [Bindings](./bindings) -- [Example app documentation](./example-apps) -- [Internal package docs](./packages) +- [Core docs](/docs/core) +- [Bindings](/docs/bindings) +- [Example app documentation](/docs/example-apps) +- [Internal package docs](/docs/packages) - Development tools - - [CLI scripts](./scripts) - - [GitHub Actions workflows](./dot-github/workflows) + - [CLI scripts](/docs/scripts) + - [GitHub Actions workflows](/docs/dot-github/workflows) - Brief explanations of the theory behind each part of the project ## How the Section is Organized diff --git a/docs/docs/js/index.md b/docs/docs/js/index.md index e64d60cfa..4d6a90243 100644 --- a/docs/docs/js/index.md +++ b/docs/docs/js/index.md @@ -123,8 +123,8 @@ const { svg } = await findContours({ ## Resources -- [Documentation](./docs/) -- [API usage](./api/) +- [Documentation](/docs/js/docs/) +- [API usage](/docs/js/api-reference/) - [GitHub repository](https://github.com/Ryan-Millard/Img2Num) - [React demo app](https://ryan-millard.github.io/Img2Num/) From fc139ab0e5cfe78744ac537aba956d6d7ed70f5a Mon Sep 17 00:00:00 2001 From: Krasner Date: Thu, 21 May 2026 17:59:56 +0000 Subject: [PATCH 04/11] doc strings and doxygen --- README.md | 1 + bindings/js/doxygen/home_page.dox | 2 +- bindings/py/src/img2num_pybind.cpp | 254 ++++++++++++++++++++++++----- docs/scripts/doxygen.js | 6 + 4 files changed, 224 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 4341b852a..63c58bfb5 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Try the [live demo](https://ryan-millard.github.io/Img2Num/)! - [C++](https://ryan-millard.github.io/Img2Num/info/docs/next/cpp/) - [C](https://ryan-millard.github.io/Img2Num/info/docs/next/c/) - [JavaScript](https://ryan-millard.github.io/Img2Num/info/docs/next/js/) +- [Python](https://ryan-millard.github.io/Img2Num/info/docs/next/python/) - [Internal docs](https://ryan-millard.github.io/Img2Num/info/docs/next/internal/) (for contributors) ### Community diff --git a/bindings/js/doxygen/home_page.dox b/bindings/js/doxygen/home_page.dox index f62b61b78..a0e920bb7 100644 --- a/bindings/js/doxygen/home_page.dox +++ b/bindings/js/doxygen/home_page.dox @@ -23,7 +23,7 @@ * To build the JavaScript/WASM bindings, follow these steps: * * \code{.sh} - * emcmake cmake -B build-wasm + * emcmake cmake -DCMAKE_BUILD_TYPE=Release -B build-wasm * cmake --build build-wasm * \endcode * diff --git a/bindings/py/src/img2num_pybind.cpp b/bindings/py/src/img2num_pybind.cpp index 5ba50bf6d..3d9805f3e 100644 --- a/bindings/py/src/img2num_pybind.cpp +++ b/bindings/py/src/img2num_pybind.cpp @@ -9,7 +9,20 @@ #include PYBIND11_MODULE(_img2num, m) { - m.doc() = "Python bindings for the img2num C++ library"; + m.doc() = R"docstring( + Python bindings for the img2num C++ library. + + This module provides access to Img2Num's image processing capabilities from Python. + All image functions operate on ``numpy.ndarray`` buffers and return new image data, + making them easy to integrate into Python-based image processing pipelines. + + Submodules + ---------- + proc : + Core image processing functions. All functions return new image data. + svg : + Functions for converting images to SVG strings. + )docstring"; // ----------------------------------------------------------------------- // All Functions return new image data @@ -27,7 +40,25 @@ PYBIND11_MODULE(_img2num, m) { return out_image; }, pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), - pybind11::arg("sigma"), "Apply Gaussian blur using FFT"); + pybind11::arg("sigma"), R"docstring( + Apply a Gaussian blur to the image using Fast Fourier Transform (FFT) for performance. + + Parameters + ---------- + image : numpy.ndarray + Input image as a uint8 numpy array. + width : int + Width of the image. + height : int + Height of the image. + sigma : float + Standard deviation for the Gaussian kernel. + + Returns + ------- + numpy.ndarray + Blurred image as a uint8 numpy array. + )docstring"); m.def( "invert_image", @@ -39,8 +70,23 @@ PYBIND11_MODULE(_img2num, m) { img2num::invert_image(out_image.mutable_data(), width, height); return out_image; }, - pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), - "Invert image colors"); + pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), R"docstring( + Invert the pixel values of an image. + + Parameters + ---------- + image : numpy.ndarray + Input image as a uint8 numpy array. + width : int + Width of the image. + height : int + Height of the image. + + Returns + ------- + numpy.ndarray + Inverted image as a uint8 numpy array. + )docstring"); m.def( "threshold_image", @@ -53,7 +99,25 @@ PYBIND11_MODULE(_img2num, m) { return out_image; }, pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), - pybind11::arg("num_thresholds"), "Apply thresholding to the image"); + pybind11::arg("num_thresholds"), R"docstring( + Apply thresholding to the image. + + Parameters + ---------- + image : numpy.ndarray + Input image as a uint8 numpy array. + width : int + Width of the image. + height : int + Height of the image. + num_thresholds : int + Number of threshold levels to apply. + + Returns + ------- + numpy.ndarray + Thresholded image as a uint8 numpy array. + )docstring"); m.def( "black_threshold_image", @@ -67,7 +131,25 @@ PYBIND11_MODULE(_img2num, m) { return out_image; }, pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), - pybind11::arg("num_thresholds"), "Apply black thresholding to the image"); + pybind11::arg("num_thresholds"), R"docstring( + Apply black thresholding to the image. + + Parameters + ---------- + image : numpy.ndarray + Input image as a uint8 numpy array. + width : int + Width of the image. + height : int + Height of the image. + num_thresholds : int + Number of threshold levels to apply. + + Returns + ------- + numpy.ndarray + Thresholded image as a uint8 numpy array. + )docstring"); m.def( "bilateral_filter", @@ -82,8 +164,29 @@ PYBIND11_MODULE(_img2num, m) { return out_image; }, pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), - pybind11::arg("sigma_spatial"), pybind11::arg("sigma_range"), pybind11::arg("color_space"), - "Apply bilateral filter"); + pybind11::arg("sigma_spatial"), pybind11::arg("sigma_range"), pybind11::arg("color_space"), R"docstring( + Apply a bilateral filter to the image. + + Parameters + ---------- + image : numpy.ndarray + Input image as a uint8 numpy array. + width : int + Width of the image. + height : int + Height of the image. + sigma_spatial : float + Standard deviation for the spatial Gaussian (proximity weight). + sigma_range : float + Standard deviation for the range Gaussian (intensity similarity weight). + color_space : int + Color space identifier (e.g., 0 for LAB, 1 for sRGB). + + Returns + ------- + numpy.ndarray + Filtered image as a uint8 numpy array. + )docstring"); m.def( "kmeans", @@ -92,56 +195,113 @@ PYBIND11_MODULE(_img2num, m) { pybind11::buffer_info data_buf = data.request(); // Allocate NumPy arrays for the outputs - auto out_data = pybind11::array_t(data_buf.shape); - auto out_labels = pybind11::array_t({(ssize_t)height, (ssize_t)width}); - - auto out_data_ptr = static_cast(out_data.mutable_data()); - auto out_labels_ptr = static_cast(out_labels.mutable_data()); + pybind11::array_t out_data(data_buf.shape); + pybind11::array_t out_labels({(ssize_t)height, (ssize_t)width}); - // Call C function - img2num::kmeans(static_cast(data_buf.ptr), out_data_ptr, - out_labels_ptr, width, height, k, max_iter, color_space); - - // Return a tuple of (out_data, out_labels) + img2num::kmeans(static_cast(data_buf.ptr), + static_cast(out_data.mutable_data()), + static_cast(out_labels.mutable_data()), width, height, k, max_iter, + color_space); return pybind11::make_tuple(out_data, out_labels); }, pybind11::arg("data"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("k"), - pybind11::arg("max_iter"), pybind11::arg("color_space"), - "Run K-Means clustering. Returns a tuple: (quantized_image, labels_array)"); + pybind11::arg("max_iter"), pybind11::arg("color_space"), R"docstring( + Perform K-means clustering on the image data. + + Parameters + ---------- + data : numpy.ndarray + Input image data as a uint8 numpy array. + width : int + Width of the image. + height : int + Height of the image. + k : int + Number of clusters to compute. + max_iter : int + Maximum number of iterations for the K-means algorithm. + color_space : int + Color space identifier for clustering. + + Returns + ------- + tuple + A tuple containing two NumPy arrays: (clustered_data, labels). + )docstring"); m.def( "labels_to_svg", - [](pybind11::array_t data, - pybind11::array_t labels, int width, int height, - int min_area) { - const uint8_t *data_ptr{static_cast(data.request().ptr)}; - const int32_t *labels_ptr{static_cast(labels.request().ptr)}; + [](pybind11::array_t data, pybind11::array_t labels, + int width, int height, int min_area) { + + const uint8_t* data_ptr{static_cast(data.request().ptr)}; + const int32_t* labels_ptr{static_cast(labels.request().ptr)}; std::string svg{img2num::labels_to_svg(data_ptr, labels_ptr, width, height, min_area)}; - pybind11::str svg_py_str(std::move(svg)); - return svg_py_str; + return pybind11::str(std::move(svg)); }, - pybind11::arg("data"), pybind11::arg("labels"), pybind11::arg("width"), - pybind11::arg("height"), pybind11::arg("min_area"), "Convert labels to SVG string"); + pybind11::arg("data"), + pybind11::arg("labels"), + pybind11::arg("width"), + pybind11::arg("height"), + pybind11::arg("min_area"), + R"docstring( + Convert a labeled image to an SVG string. + + Parameters + ---------- + data : numpy.ndarray + Input image data as a uint8 numpy array. + labels : numpy.ndarray + Label map as an int32 numpy array. + width : int + Width of the image. + height : int + Height of the image. + min_area : int + Minimum cluster area to include in the SVG. + + Returns + ------- + str + An SVG string containing data roughly approximate to the input image. + )docstring"); - // ---------------------- Config Structs ---------------------- - pybind11::class_ config(m, "ImageToSvgConfig"); + // ------------------------------------------ Config Structs ---------------------- + pybind11::class_ config(m, "ImageToSvgConfig", R"docstring( + Configuration options for image_to_svg. + + This class holds parameters for bilateral filtering, K-means clustering, + and SVG generation. All parameters have sensible defaults. + )docstring"); pybind11::class_(config, - "BilateralFilterConfig") + "BilateralFilterConfig", R"docstring( + Configuration for the bilateral filter used in image_to_svg. + )docstring") .def(pybind11::init<>()) .def_readwrite("sigma_spatial", - &img2num::ImageToSvgConfig::BilateralFilterConfig::sigma_spatial) + &img2num::ImageToSvgConfig::BilateralFilterConfig::sigma_spatial, R"docstring( + Standard deviation for spatial Gaussian (proximity weight). Default: 3.0 + )docstring") .def_readwrite("sigma_range", - &img2num::ImageToSvgConfig::BilateralFilterConfig::sigma_range) + &img2num::ImageToSvgConfig::BilateralFilterConfig::sigma_range, R"docstring( + Standard deviation for range Gaussian (intensity similarity weight). Default: 50.0 + )docstring") .def("__repr__", [](const img2num::ImageToSvgConfig::BilateralFilterConfig &c) { return "{'sigma_spatial': " + std::to_string(c.sigma_spatial) + ", 'sigma_range': " + std::to_string(c.sigma_range) + "}"; }); - pybind11::class_(config, "KMeansConfig") + pybind11::class_(config, "KMeansConfig", R"docstring( + Configuration for the K-means clustering used in image_to_svg. + )docstring") .def(pybind11::init<>()) - .def_readwrite("k", &img2num::ImageToSvgConfig::KMeansConfig::k) - .def_readwrite("max_iter", &img2num::ImageToSvgConfig::KMeansConfig::max_iter) + .def_readwrite("k", &img2num::ImageToSvgConfig::KMeansConfig::k, R"docstring( + Number of clusters to compute. Roughly represents number of unique colors discovered. Default: 16 + )docstring") + .def_readwrite("max_iter", &img2num::ImageToSvgConfig::KMeansConfig::max_iter, R"docstring( + Maximum number of iterations for the K-means algorithm. Default: 100 + )docstring") .def("__repr__", [](const img2num::ImageToSvgConfig::KMeansConfig &c) { return "{'k': " + std::to_string(c.k) + ", 'max_iter': " + std::to_string(c.max_iter) + "}"; @@ -206,5 +366,23 @@ PYBIND11_MODULE(_img2num, m) { pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("cfg"), - "Convert Image to SVG string"); + R"docstring( + Convert Image to SVG string. + + Parameters + ---------- + data : numpy.ndarray + Input image buffer. + width : int + Width of the image. + height : int + Height of the image. + cfg : ImageToSvgConfig + Configuration object containing filter and clustering parameters. + + Returns + ------- + str + SVG string representation of the image. + )docstring"); } diff --git a/docs/scripts/doxygen.js b/docs/scripts/doxygen.js index 60e58b2cd..d1b22ba00 100644 --- a/docs/scripts/doxygen.js +++ b/docs/scripts/doxygen.js @@ -11,6 +11,7 @@ const OUTPUT_PARENT_DIR = join(ROOT_DIR, "static/docs"); const CORE_DIR = join("core"); const JS_BINDINGS_DIR = join("bindings", "js"); const C_BINDINGS_DIR = join("bindings", "c"); +const PY_BINDINGS_DIR = join("bindings", "py"); const DOXYFILES = [ { @@ -28,6 +29,11 @@ const DOXYFILES = [ srcDir: JS_BINDINGS_DIR, outDir: join(OUTPUT_PARENT_DIR, "internal", "bindings", "js", "api") }, + { + fileName: "Doxyfile.internal", + srcDir: PY_BINDINGS_DIR, + outDir: join(OUTPUT_PARENT_DIR, "internal", "bindings", "py", "api") + }, { fileName: "Doxyfile.public", srcDir: C_BINDINGS_DIR, From ed49ba219ade0c7c18841c7fc8cae81cc9a6b46e Mon Sep 17 00:00:00 2001 From: Krasner Date: Thu, 21 May 2026 18:00:17 +0000 Subject: [PATCH 05/11] doc strings and doxygen --- bindings/py/Doxyfile.internal | 14 +++++ bindings/py/doxygen/home_page.dox | 95 +++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 bindings/py/Doxyfile.internal create mode 100644 bindings/py/doxygen/home_page.dox diff --git a/bindings/py/Doxyfile.internal b/bindings/py/Doxyfile.internal new file mode 100644 index 000000000..3ae6e51f1 --- /dev/null +++ b/bindings/py/Doxyfile.internal @@ -0,0 +1,14 @@ +@INCLUDE = ../../doxygen/Doxyfile.base + +PROJECT_NAME = "Img2Num Python Bindings (Internal Developer Docs)" + +PROJECT_NUMBER = dev + +INPUT = src ../../doxygen/*.dox doxygen/home_page.dox +OUTPUT_DIRECTORY = ../../docs/static/docs/internal/bindings/py/api + +RECURSIVE = YES + +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +INTERNAL_DOCS = YES diff --git a/bindings/py/doxygen/home_page.dox b/bindings/py/doxygen/home_page.dox new file mode 100644 index 000000000..74de1c441 --- /dev/null +++ b/bindings/py/doxygen/home_page.dox @@ -0,0 +1,95 @@ +/*! \mainpage Img2Num Python Bindings + * + * \section intro_sec Introduction + * + * The **Img2Num Python Bindings** provide a Python interface to the core Img2Num + * image processing library via pybind11. These bindings wrap the underlying C++ + * functionality, exposing image processing operations such as filtering, clustering, + * thresholding, and SVG conversion to Python code. + * + * All functions operate on `numpy.ndarray` buffers and return new image data, making + * them easy to integrate into Python-based image processing pipelines. + * + * \section features_sec Key Features + * + * The Python bindings expose the following core capabilities: + * - **FFT-based Gaussian blur** — Fast frequency-domain blurring + * - **Image inversion** — Invert pixel values + * - **Thresholding** — Standard and black-thresholding operations + * - **K-means clustering** — Pixel clustering for color quantization + * - **Bilateral filtering** — Edge-preserving smoothing + * - **Label-to-SVG conversion** — Convert labeled images to SVG strings + * - **Image-to-SVG conversion** — Full image vectorization with configurable parameters + * - **ImageToSvgConfig** — Python-accessible configuration for SVG generation + * + * \section building_sec Building the Python Bindings + * + * The Python bindings are built using CMake from the project root: + * + * \code{.sh} + * cmake -B build . + * cmake --build build + * \endcode + * + * \section install_sec Installation + * + * Install the bindings to your system: + * + * \code{.sh} + * cmake --install build + * \endcode + * + * The compiled `_img2num` module will be available for import in Python: + * + * \code{.py} + * import _img2num + * \endcode + * + * \section usage_sec Usage Example + * + * \code{.py} + * import numpy as np + * import _img2num + * + * # Load image as uint8 numpy array + * image = np.array([...], dtype=np.uint8).reshape((height, width, 3)) + * + * # Apply Gaussian blur + * blurred = _img2num.gaussian_blur_fft(image, width, height, sigma=2.0) + * + * # Invert colors + * inverted = _img2num.invert_image(image, width, height) + * + * # Threshold + * thresholded = _img2num.threshold_image(image, width, height, num_thresholds=4) + * + * # K-means clustering + * clustered_data, labels = _img2num.kmeans(image, width, height, k=8, max_iter=50) + * + * # Bilateral filtering + * filtered = _img2num.bilateral_filter(image, width, height, sigma_spatial=3.0, sigma_range=50.0) + * + * # SVG conversion + * config = _img2num.ImageToSvgConfig() + * svg_str = _img2num.image_to_svg(image, width, height, config) + * \endcode + * + * \section api_sec API Reference + * + * Browse the detailed function and class documentation: + * - \ref img2num_functions "Core Image Processing Functions" + * - \ref img2num_classes "Configuration Classes" + */ + +/** \defgroup img2num_functions Image Processing Functions + * @ingroup mainpage + * @brief Image processing functions exposed via Python bindings. + * @{ + */ + +/** \defgroup img2num_classes Configuration Classes + * @ingroup mainpage + * @brief Configuration classes for image processing and SVG generation. + * @{ + */ + From b37467de8f9efcc933a824d0f1e2289ce55af752 Mon Sep 17 00:00:00 2001 From: Krasner Date: Fri, 22 May 2026 02:56:14 +0000 Subject: [PATCH 06/11] fix docusaurus build... but is it correct? --- docs/docs/api-reference.md | 8 ++++---- docs/docs/contributing/index.md | 4 ++-- docs/docs/getting-started.md | 6 +++--- docs/docs/index.md | 22 +++++++++++----------- docs/docs/internal/index.md | 12 ++++++------ docs/docs/js/index.md | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md index a185a1238..87c2d519d 100644 --- a/docs/docs/api-reference.md +++ b/docs/docs/api-reference.md @@ -10,10 +10,10 @@ Img2Num provides bindings for multiple languages. Choose the one that fits your | Language | Docs | | :------------- | :--------------------------------------------- | -| **JavaScript** | [JS API Reference](/docs/js/api-reference) | -| **C++** | [C++ API Reference](/docs/cpp/api-reference) | -| **C** | [C API Reference](/docs/c/api-reference) | -| **Python** | [Python API Reference](/docs/python/api-reference) | +| **JavaScript** | [JS API Reference](/docs/next/js/js-api-reference) | +| **C++** | [C++ API Reference](/docs/next/cpp/cpp-api-reference) | +| **C** | [C API Reference](/docs/next/c/c-api-reference) | +| **Python** | [Python API Reference](/docs/next/python/python-api-reference) | ## Common Concepts Across All Bindings diff --git a/docs/docs/contributing/index.md b/docs/docs/contributing/index.md index 109df1572..46bf2fcc9 100644 --- a/docs/docs/contributing/index.md +++ b/docs/docs/contributing/index.md @@ -10,7 +10,7 @@ First off, thank you for considering contributing to Img2Num! We welcome any kin ## Code of Conduct -Please review and adhere to our [Code of Conduct](/docs/code-of-conduct.md) to help foster an open and welcoming environment. +Please review and adhere to our [Code of Conduct](/docs/contributing/code-of-conduct.md) to help foster an open and welcoming environment. ## Reporting Issues @@ -50,6 +50,6 @@ When a claim expires: ## Development Setup -The [Setup & Dependencies](/docs/setup-and-dependencies) section shows how to clone and run the application for the first time. +The [Setup & Dependencies](/docs/next/contributing/setup-and-dependencies) section shows how to clone and run the application for the first time. The [scripts](../internal/scripts) section shows all of the available scripts you may find useful whilst working on Img2Num's source code as well as a helpful way to find specific scripts if you have forgotten one. diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index 0f5c1eafe..02e1534fc 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -82,6 +82,6 @@ flowchart LR ## Next steps -- [Concepts](/docs/concepts) — learn about color spaces, filtering, and contours. -- [API Reference](/docs/api-reference) — full parameter documentation. -- [Performance](/docs/performance) — tips for speeding up your pipeline. +- [Concepts](/docs/next/concepts) — learn about color spaces, filtering, and contours. +- [API Reference](/docs/next/api-reference) — full parameter documentation. +- [Performance](/docs/next/performance) — tips for speeding up your pipeline. diff --git a/docs/docs/index.md b/docs/docs/index.md index b363a6f7d..ea88d3494 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -17,21 +17,21 @@ Img2Num is a lightweight, high-performance library for converting raster images ## Getting Started -1. **[Installation](/docs/installation)** — Install Img2Num for your platform. -2. **[Getting Started](/docs/getting-started)** — Your first conversion in under 5 minutes. -3. **[Concepts](/docs/concepts)** — Learn about color spaces, filtering, and contours. -4. **[API Reference](/docs/api-reference)** — Full documentation for all bindings. -5. **[Performance](/docs/performance)** — Tips for speeding up your pipeline. -6. **[Troubleshooting](/docs/troubleshooting)** — Common issues and fixes. +1. **[Installation](/docs/next/installation)** — Install Img2Num for your platform. +2. **[Getting Started](/docs/next/getting-started)** — Your first conversion in under 5 minutes. +3. **[Concepts](/docs/next/concepts)** — Learn about color spaces, filtering, and contours. +4. **[API Reference](/docs/next/api-reference)** — Full documentation for all bindings. +5. **[Performance](/docs/next/performance)** — Tips for speeding up your pipeline. +6. **[Troubleshooting](/docs/next/troubleshooting)** — Common issues and fixes. ## API Bindings | Binding | Status | Docs | | :-------------------- | :------------ | :--------------------------------------------- | -| **JavaScript (WASM)** | ✅ Production | [JS API Reference](/docs/js/api-reference) | -| **C++** | ✅ Production | [C++ API Reference](/docs/cpp/api-reference) | -| **C** | ✅ Production | [C API Reference](/docs/c/api-reference) | -| **Python** | 🟡 Early | [Python API Reference](/docs/python/api-reference) | +| **JavaScript (WASM)** | ✅ Production | [JS API Reference](/docs/next/js/js-api-reference) | +| **C++** | ✅ Production | [C++ API Reference](/docs/next/cpp/cpp-api-reference) | +| **C** | ✅ Production | [C API Reference](/docs/next/c/c-api-reference) | +| **Python** | 🟡 Early | [Python API Reference](/docs/next/python/python-api-reference) | ## Changelog @@ -40,7 +40,7 @@ Our [changelog](/changelog) is quite empty right now since we haven't had our fi --- We hope you enjoy using **Img2Num**! -For issues or contributions, see our [contributors guide](/docs/contributing) or visit our +For issues or contributions, see our [contributors guide](/docs/next/contributing) or visit our [GitHub repository](https://github.com/Ryan-Millard/Img2Num/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22). :::note diff --git a/docs/docs/internal/index.md b/docs/docs/internal/index.md index 719f145cb..39d43ec94 100644 --- a/docs/docs/internal/index.md +++ b/docs/docs/internal/index.md @@ -29,13 +29,13 @@ This documentation serves three main goals: ## What You Will Find Here -- [Core docs](/docs/core) -- [Bindings](/docs/bindings) -- [Example app documentation](/docs/example-apps) -- [Internal package docs](/docs/packages) +- [Core docs](/docs/next/internal/core) +- [Bindings](/docs/next/internal/bindings) +- [Example app documentation](/docs/next/internal/example-apps) +- [Internal package docs](/docs/next/internal/packages) - Development tools - - [CLI scripts](/docs/scripts) - - [GitHub Actions workflows](/docs/dot-github/workflows) + - [CLI scripts](/docs/next/internal/scripts) + - [GitHub Actions workflows](./dot-github/workflows) - Brief explanations of the theory behind each part of the project ## How the Section is Organized diff --git a/docs/docs/js/index.md b/docs/docs/js/index.md index 4d6a90243..3d57ae018 100644 --- a/docs/docs/js/index.md +++ b/docs/docs/js/index.md @@ -123,8 +123,8 @@ const { svg } = await findContours({ ## Resources -- [Documentation](/docs/js/docs/) -- [API usage](/docs/js/api-reference/) +- [Documentation](/docs/next/js/docs/) +- [API usage](/docs/next/js/js-api-reference/) - [GitHub repository](https://github.com/Ryan-Millard/Img2Num) - [React demo app](https://ryan-millard.github.io/Img2Num/) From 5a68a7d24e77bbab6971da18c0a224be3c9e92c4 Mon Sep 17 00:00:00 2001 From: Krasner Date: Fri, 22 May 2026 03:01:23 +0000 Subject: [PATCH 07/11] format docs --- bindings/c/include/cimg2num.h | 1 - bindings/c/src/cimg2num.cpp | 39 ++++++++----------------- bindings/py/src/img2num_pybind.cpp | 47 ++++++++++++++---------------- docs/docs/api-reference.md | 10 +++---- docs/docs/index.md | 10 +++---- 5 files changed, 44 insertions(+), 63 deletions(-) diff --git a/bindings/c/include/cimg2num.h b/bindings/c/include/cimg2num.h index 4da5d36f1..b671e2852 100644 --- a/bindings/c/include/cimg2num.h +++ b/bindings/c/include/cimg2num.h @@ -19,7 +19,6 @@ extern "C" { /// @brief Configuration options for image_to_svg. /// @ingroup CIMG2NUM_H typedef struct img2num_ImageToSvgConfig { - /// Configuration settings for the bilateral filter in image_to_svg. struct BilateralFilterConfig { /// Standard deviation for spatial Gaussian (proximity weight). diff --git a/bindings/c/src/cimg2num.cpp b/bindings/c/src/cimg2num.cpp index 74777be72..ef4503881 100644 --- a/bindings/c/src/cimg2num.cpp +++ b/bindings/c/src/cimg2num.cpp @@ -8,33 +8,19 @@ extern "C" { static img2num::ImageToSvgConfig to_cpp(const img2num_ImageToSvgConfig &c) { - return { - .bilateral_filter{ - .sigma_spatial = c.bilateral_filter.sigma_spatial, - .sigma_range = c.bilateral_filter.sigma_range - }, - .kmeans{ - .k = c.kmeans.k, - .max_iter = c.kmeans.max_iter - }, - .min_cluster_area = c.min_cluster_area, - .color_space = c.color_space - }; + return {.bilateral_filter{.sigma_spatial = c.bilateral_filter.sigma_spatial, + .sigma_range = c.bilateral_filter.sigma_range}, + .kmeans{.k = c.kmeans.k, .max_iter = c.kmeans.max_iter}, + .min_cluster_area = c.min_cluster_area, + .color_space = c.color_space}; } static img2num_ImageToSvgConfig to_c(const img2num::ImageToSvgConfig &cpp) { - return { - .bilateral_filter{ - .sigma_spatial = cpp.bilateral_filter.sigma_spatial, - .sigma_range = cpp.bilateral_filter.sigma_range - }, - .kmeans{ - .k = cpp.kmeans.k, - .max_iter = cpp.kmeans.max_iter - }, - .min_cluster_area = cpp.min_cluster_area, - .color_space = cpp.color_space - }; + return {.bilateral_filter{.sigma_spatial = cpp.bilateral_filter.sigma_spatial, + .sigma_range = cpp.bilateral_filter.sigma_range}, + .kmeans{.k = cpp.kmeans.k, .max_iter = cpp.kmeans.max_iter}, + .min_cluster_area = cpp.min_cluster_area, + .color_space = cpp.color_space}; } img2num_ImageToSvgConfig img2num_ImageToSvgConfig_default(void) { @@ -101,7 +87,7 @@ char *img2num_image_to_svg(const uint8_t *data, const int width, const int heigh img2num::clear_last_error_and_catch( [&](const uint8_t *d, const int w, const int h) { - std::string svg{ img2num::image_to_svg(d, w, h, to_cpp(cfg)) }; + std::string svg{img2num::image_to_svg(d, w, h, to_cpp(cfg))}; result = static_cast(std::malloc(svg.size() + 1)); if (!result) { @@ -109,8 +95,7 @@ char *img2num_image_to_svg(const uint8_t *data, const int width, const int heigh } std::memcpy(result, svg.c_str(), svg.size() + 1); }, - data, width, height - ); + data, width, height); return result; } diff --git a/bindings/py/src/img2num_pybind.cpp b/bindings/py/src/img2num_pybind.cpp index 3d9805f3e..7c8cd7067 100644 --- a/bindings/py/src/img2num_pybind.cpp +++ b/bindings/py/src/img2num_pybind.cpp @@ -5,8 +5,8 @@ #include #include -#include #include +#include PYBIND11_MODULE(_img2num, m) { m.doc() = R"docstring( @@ -164,7 +164,8 @@ PYBIND11_MODULE(_img2num, m) { return out_image; }, pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), - pybind11::arg("sigma_spatial"), pybind11::arg("sigma_range"), pybind11::arg("color_space"), R"docstring( + pybind11::arg("sigma_spatial"), pybind11::arg("sigma_range"), pybind11::arg("color_space"), + R"docstring( Apply a bilateral filter to the image. Parameters @@ -196,12 +197,13 @@ PYBIND11_MODULE(_img2num, m) { // Allocate NumPy arrays for the outputs pybind11::array_t out_data(data_buf.shape); - pybind11::array_t out_labels({(ssize_t)height, (ssize_t)width}); + pybind11::array_t out_labels( + {(ssize_t)height, (ssize_t)width}); img2num::kmeans(static_cast(data_buf.ptr), static_cast(out_data.mutable_data()), - static_cast(out_labels.mutable_data()), width, height, k, max_iter, - color_space); + static_cast(out_labels.mutable_data()), width, height, k, + max_iter, color_space); return pybind11::make_tuple(out_data, out_labels); }, pybind11::arg("data"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("k"), @@ -231,21 +233,18 @@ PYBIND11_MODULE(_img2num, m) { m.def( "labels_to_svg", - [](pybind11::array_t data, pybind11::array_t labels, - int width, int height, int min_area) { - - const uint8_t* data_ptr{static_cast(data.request().ptr)}; - const int32_t* labels_ptr{static_cast(labels.request().ptr)}; + [](pybind11::array_t data, + pybind11::array_t labels, int width, int height, + int min_area) { + const uint8_t *data_ptr{static_cast(data.request().ptr)}; + const int32_t *labels_ptr{static_cast(labels.request().ptr)}; std::string svg{img2num::labels_to_svg(data_ptr, labels_ptr, width, height, min_area)}; return pybind11::str(std::move(svg)); }, - pybind11::arg("data"), - pybind11::arg("labels"), - pybind11::arg("width"), - pybind11::arg("height"), - pybind11::arg("min_area"), + pybind11::arg("data"), pybind11::arg("labels"), pybind11::arg("width"), + pybind11::arg("height"), pybind11::arg("min_area"), R"docstring( Convert a labeled image to an SVG string. @@ -275,13 +274,14 @@ PYBIND11_MODULE(_img2num, m) { This class holds parameters for bilateral filtering, K-means clustering, and SVG generation. All parameters have sensible defaults. )docstring"); - pybind11::class_(config, - "BilateralFilterConfig", R"docstring( + pybind11::class_( + config, "BilateralFilterConfig", R"docstring( Configuration for the bilateral filter used in image_to_svg. )docstring") .def(pybind11::init<>()) .def_readwrite("sigma_spatial", - &img2num::ImageToSvgConfig::BilateralFilterConfig::sigma_spatial, R"docstring( + &img2num::ImageToSvgConfig::BilateralFilterConfig::sigma_spatial, + R"docstring( Standard deviation for spatial Gaussian (proximity weight). Default: 3.0 )docstring") .def_readwrite("sigma_range", @@ -332,7 +332,7 @@ PYBIND11_MODULE(_img2num, m) { return c; }), pybind11::arg("bilateral_filter") = pybind11::dict(), // Defaults to empty dict - pybind11::arg("kmeans") = pybind11::dict() // Defaults to empty dict + pybind11::arg("kmeans") = pybind11::dict() // Defaults to empty dict ) .def_readwrite("bilateral_filter", &img2num::ImageToSvgConfig::bilateral_filter) .def_readwrite("min_cluster_area", &img2num::ImageToSvgConfig::min_cluster_area) @@ -354,17 +354,14 @@ PYBIND11_MODULE(_img2num, m) { m.def( "image_to_svg", [](pybind11::array_t data, int width, int height, - const img2num::ImageToSvgConfig& cfg) { - - const uint8_t* data_ptr{static_cast(data.request().ptr)}; + const img2num::ImageToSvgConfig &cfg) { + const uint8_t *data_ptr{static_cast(data.request().ptr)}; std::string svg{img2num::image_to_svg(data_ptr, width, height, cfg)}; return pybind11::str(std::move(svg)); }, - pybind11::arg("data"), - pybind11::arg("width"), - pybind11::arg("height"), + pybind11::arg("data"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("cfg"), R"docstring( Convert Image to SVG string. diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md index 87c2d519d..9ab626ae9 100644 --- a/docs/docs/api-reference.md +++ b/docs/docs/api-reference.md @@ -8,11 +8,11 @@ sidebar_position: 6 Img2Num provides bindings for multiple languages. Choose the one that fits your workflow: -| Language | Docs | -| :------------- | :--------------------------------------------- | -| **JavaScript** | [JS API Reference](/docs/next/js/js-api-reference) | -| **C++** | [C++ API Reference](/docs/next/cpp/cpp-api-reference) | -| **C** | [C API Reference](/docs/next/c/c-api-reference) | +| Language | Docs | +| :------------- | :------------------------------------------------------------- | +| **JavaScript** | [JS API Reference](/docs/next/js/js-api-reference) | +| **C++** | [C++ API Reference](/docs/next/cpp/cpp-api-reference) | +| **C** | [C API Reference](/docs/next/c/c-api-reference) | | **Python** | [Python API Reference](/docs/next/python/python-api-reference) | ## Common Concepts Across All Bindings diff --git a/docs/docs/index.md b/docs/docs/index.md index ea88d3494..15f9ba668 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -26,11 +26,11 @@ Img2Num is a lightweight, high-performance library for converting raster images ## API Bindings -| Binding | Status | Docs | -| :-------------------- | :------------ | :--------------------------------------------- | -| **JavaScript (WASM)** | ✅ Production | [JS API Reference](/docs/next/js/js-api-reference) | -| **C++** | ✅ Production | [C++ API Reference](/docs/next/cpp/cpp-api-reference) | -| **C** | ✅ Production | [C API Reference](/docs/next/c/c-api-reference) | +| Binding | Status | Docs | +| :-------------------- | :------------ | :------------------------------------------------------------- | +| **JavaScript (WASM)** | ✅ Production | [JS API Reference](/docs/next/js/js-api-reference) | +| **C++** | ✅ Production | [C++ API Reference](/docs/next/cpp/cpp-api-reference) | +| **C** | ✅ Production | [C API Reference](/docs/next/c/c-api-reference) | | **Python** | 🟡 Early | [Python API Reference](/docs/next/python/python-api-reference) | ## Changelog From 3b6ed396ae166922e4c6f0e498ecb0b09b20435e Mon Sep 17 00:00:00 2001 From: Krasner Date: Fri, 22 May 2026 03:20:28 +0000 Subject: [PATCH 08/11] bindings/py docs --- .../internal/bindings/py/api-reference.md | 22 ++++++ docs/docs/internal/bindings/py/index.md | 77 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 docs/docs/internal/bindings/py/api-reference.md create mode 100644 docs/docs/internal/bindings/py/index.md diff --git a/docs/docs/internal/bindings/py/api-reference.md b/docs/docs/internal/bindings/py/api-reference.md new file mode 100644 index 000000000..3b42c3748 --- /dev/null +++ b/docs/docs/internal/bindings/py/api-reference.md @@ -0,0 +1,22 @@ +--- +title: Python API Reference +description: > + This page provides a full-page view of the Img2Num Python bindings API reference + generated by Doxygen. Use the fullscreen button to expand the view + for easier navigation and code browsing. +--- + +import FullscreenIframe from '@site/src/components/FullscreenIframe'; + +> Don't like iframes? +Visit the{' '} + { e.preventDefault(); window.location.href = "/Img2Num/info/docs/internal/bindings/py/api/"; }}> Doxygen documentation {' '} directly. + + + +## About this page + +This page is a direct proxy for the{' '} { e.preventDefault(); window.location.href = "/Img2Num/info/docs/internal/bindings/py/api/"; }}> Doxygen documentation generated from the `bindings/py` directory. diff --git a/docs/docs/internal/bindings/py/index.md b/docs/docs/internal/bindings/py/index.md new file mode 100644 index 000000000..fdde854a0 --- /dev/null +++ b/docs/docs/internal/bindings/py/index.md @@ -0,0 +1,77 @@ +--- +title: Img2Num Python Bindings +sidebar_label: py +keywords: [Img2Num, Python bindings, image processing, SVG conversion, gaussian blur, k-means clustering, bilateral filter] +description: Internal documentation for the Img2Num Python bindings, providing an overview of available functions, building instructions, and usage examples. +--- + +# Img2Num Python Bindings + +The **Img2Num Python Bindings** provide a Python interface to the core Img2Num image processing library via pybind11. These bindings wrap the underlying C++ functions, exposing high-performance image processing operations to Python projects. + +--- + +## Overview + +The bindings wrap the underlying C++ functions (from [`core/`](../../core)) using pybind11 and operate on `numpy.ndarray` buffers. They provide access to key image processing operations such as filtering, clustering, and SVG conversion. + +## Key Functions + +* `gaussian_blur_fft` — Apply FFT-based Gaussian blur +* `invert_image` — Invert pixel values in an image +* `threshold_image` — Apply thresholding to an image +* `black_threshold_image` — Apply black-thresholding +* `kmeans` — Perform k-means clustering on image pixels +* `bilateral_filter` — Apply bilateral filtering +* `labels_to_svg` — Convert labeled image to SVG +* `image_to_svg` — Convert image to SVG with configurable parameters + +Each function is fully documented with Doxygen and mirrors the corresponding C++ function in `core/img2num.h`. + +## Building the Python Bindings + +```bash title="Run this in the root of the project" +cmake -B build . +cmake --build build +cmake --install build +``` + +> `cmake --install build` might need elevated permissions, but that shouldn't be a problem in the Docker container. + +* The compiled `_img2num` module is installed under `img2num/`. +* Ensure that the core `Img2Num` library is built and accessible. + +## Usage Example + +:::important Proper Examples +See the [`example-apps/`](https://github.com/Ryan-Millard/Img2Num/tree/main/example-apps/) folder for the most up-to-date usage examples. +::: + +```python title="Applying basic image processing operations using the Python API" +import numpy as np +from img2num import ( + gaussian_blur_fft, + invert_image, + threshold_image, + image_to_svg, +) + +# Load image as uint8 numpy array (H, W, C) +image = np.zeros((256, 256, 3), dtype=np.uint8) + +# Apply Gaussian blur +blurred = gaussian_blur_fft(image, sigma=1.5) + +# Invert colors +inverted = invert_image(blurred) + +# Threshold +thresholded = threshold_image(inverted, num_thresholds=4) + +# SVG conversion +svg_str = image_to_svg(thresholded) +``` + +## Documentation + +The Doxygen documentation provides detailed descriptions of all functions, their parameters, and usage examples. Refer to the [generated docs](./api-reference) for guidance on integrating the bindings into internal projects. From 6c7068906d2b397fc2a03270a434247397f9980d Mon Sep 17 00:00:00 2001 From: Krasner Date: Sun, 24 May 2026 13:54:34 +0000 Subject: [PATCH 09/11] mermaid format --- docs/docs/api-reference.md | 26 ++++++++++++-------------- docs/docs/js/docs/index.md | 37 +++++++++++++++---------------------- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md index 9ab626ae9..686dd5401 100644 --- a/docs/docs/api-reference.md +++ b/docs/docs/api-reference.md @@ -37,18 +37,16 @@ All APIs share these core concepts: ## Pipeline Flow -``` -[Raster Image] - │ - ▼ -[ Bilateral Filter ] (sigma_spatial, sigma_range) - │ - ▼ -[ K-Means Clustering ] (k, max_iter, color_space) - │ - ▼ -[ Contour Detection ] (min_area) - │ - ▼ -[ SVG Output ] +```mermaid +graph TD + A[Raster Image] --> B[Bilateral Filter] + B --> C[K-Means Clustering] + C --> D[Contour Detection] + D --> E[SVG Output] + + subgraph Parameters + B --- P1(sigma_spatial, sigma_range) + C --- P2(k, max_iter, color_space) + D --- P3(min_area) + end ``` diff --git a/docs/docs/js/docs/index.md b/docs/docs/js/docs/index.md index 6df95c8c1..9d542320b 100644 --- a/docs/docs/js/docs/index.md +++ b/docs/docs/js/docs/index.md @@ -4,28 +4,21 @@ The JavaScript binding wraps Img2Num's WASM core in a clean, async API. It runs ## Architecture -``` -Browser / Node.js - │ - ▼ -┌─────────────────────────┐ -│ safeWasmWrappers.js │ ← Public API (imageToSvg, kmeans, etc.) -└─────────────────────────┘ - │ - ▼ -┌─────────────────────────┐ -│ wasmClient.js │ ← Worker communication (postMessage) -└─────────────────────────┘ - │ - ▼ -┌─────────────────────────┐ -│ wasmWorker.js │ ← WASM module loader & message handler -└─────────────────────────┘ - │ - ▼ -┌─────────────────────────┐ -│ img2num_core.wasm │ ← Emscripten-compiled core (C++ → WASM) -└─────────────────────────┘ +```mermaid +graph TD + A([Browser / Node.js]) --> B + + B["safeWasmWrappers.js
Public API (imageToSvg, kmeans, etc.)"] + C["wasmClient.js
Worker communication (postMessage)"] + D["wasmWorker.js
WASM module loader & message handler"] + E[["img2num_core.wasm
Emscripten-compiled core (C++ → WASM)"]] + + B --> C + C --> D + D --> E + + %% Accent the WASM core binary box + style E fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px ``` Key files: From 6bc77fdf41161b94051671bbab7aee3a09ed2b16 Mon Sep 17 00:00:00 2001 From: Krasner Date: Sun, 24 May 2026 13:59:48 +0000 Subject: [PATCH 10/11] formatting --- docs/docs/js/docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/js/docs/index.md b/docs/docs/js/docs/index.md index 9d542320b..1f571af57 100644 --- a/docs/docs/js/docs/index.md +++ b/docs/docs/js/docs/index.md @@ -7,7 +7,7 @@ The JavaScript binding wraps Img2Num's WASM core in a clean, async API. It runs ```mermaid graph TD A([Browser / Node.js]) --> B - + B["safeWasmWrappers.js
Public API (imageToSvg, kmeans, etc.)"] C["wasmClient.js
Worker communication (postMessage)"] D["wasmWorker.js
WASM module loader & message handler"] From c5de57119dc346090fedb0a70bf5e28a1305a191 Mon Sep 17 00:00:00 2001 From: Krasner Date: Mon, 1 Jun 2026 02:08:58 +0000 Subject: [PATCH 11/11] add dev ownership to /opt/emsdk/ --- Dockerfile.dev | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile.dev b/Dockerfile.dev index 5328e33a9..59522f47a 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -81,6 +81,7 @@ ENV EMSDK=$EMSDK_DIR # Auto-load emsdk in all shells RUN echo "source /opt/emsdk/emsdk_env.sh" >> /etc/bash.bashrc +RUN chown -R dev:dev /opt/emsdk/ # -------------------------------------------------------------------------------------------------------------- # Dawn dependencies RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \