Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b8f2586
chore(deps-js): update all pnpm dependencies
Ryan-Millard Apr 23, 2026
0f0c4d5
fix(docs): build error from not installing @docusaurus/faster
Ryan-Millard Apr 25, 2026
80eef15
style(react-example): run formatting
Ryan-Millard Apr 25, 2026
d473c8e
Merge branch 'main' into chore/deps/js
Ryan-Millard Apr 25, 2026
22a27bd
fix(docs): convert HTML-style comments to React-style to fix build er…
Ryan-Millard Apr 25, 2026
1629a78
chore(example-app): (React) cleanup App.jsx imports
Ryan-Millard Apr 25, 2026
21072ee
docs(dotenv): silence dotenv during builds
Ryan-Millard Apr 25, 2026
d591e9f
fix(example-app): (React) wrap GitHub SVG to ensure appropriate sizing
Ryan-Millard Apr 25, 2026
2f5efd4
chore(deps): remove unused react-helmet-async
Ryan-Millard Apr 25, 2026
c0507d5
style(format): format all files
Ryan-Millard Apr 25, 2026
aa2aee1
fix(docs): broken build caused by bad comments
Ryan-Millard Apr 25, 2026
ff415ed
fix(formatting): fix Prettier format, update C++ formatting, format a…
Ryan-Millard Apr 25, 2026
d11bbd5
fix(docs): build errors due to linting & style
Ryan-Millard Apr 25, 2026
65603e3
style(format): format docs files
Ryan-Millard Apr 25, 2026
a238360
revert(docs): Docusaurus is a problem. How can they change their synt…
Ryan-Millard Apr 25, 2026
2028061
vkjgf
Ryan-Millard Apr 25, 2026
b699bb1
fix(docs): syntax error from new Docusaurus version
Ryan-Millard Apr 29, 2026
fea3df6
style(format): fix docs formatting
Ryan-Millard Apr 29, 2026
060c669
chore(deps): upgrade docs deps
Ryan-Millard Apr 29, 2026
bc4105d
chore(deps): upgrade all pnpm deps
Ryan-Millard Apr 29, 2026
42cf3b2
Merge branch 'main' into chore/deps/js
Ryan-Millard Apr 29, 2026
4efcdc7
style(format): format all files
Ryan-Millard Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,14 @@ docs/static/js/api.json
docs/docs/js/api/
example-apps/react-js/src/data/contributor-credits.json
third_party/
.venv
.img2num-state
.npmrc
LICENSE*
example-apps/*-py/
example-apps/*-cpp/
example-apps/*-c/
bindings/py/
bindings/c/
packages/py
docs/static/
11 changes: 10 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
{}
{
"overrides": [
{
"files": ["docs/**/*.md"],
"options": {
"parser": "mdx"
}
}
]
}
4 changes: 2 additions & 2 deletions bindings/c/src/cimg2num.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "cimg2num.h"

#include <cstring>

#include "img2num.h"
#include "img2num/Error.h"

#include <cstring>

extern "C" {

void img2num_gaussian_blur_fft(uint8_t *image, size_t width, size_t height, double sigma) {
Expand Down
40 changes: 20 additions & 20 deletions bindings/py/src/img2num_pybind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ PYBIND11_MODULE(_img2num, m) {
img2num::gaussian_blur_fft(out_image.mutable_data(), width, height, sigma);
return out_image;
},
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("sigma"),
"Apply Gaussian blur using FFT");
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"),
pybind11::arg("sigma"), "Apply Gaussian blur using FFT");

m.def(
"invert_image",
Expand All @@ -48,8 +48,8 @@ PYBIND11_MODULE(_img2num, m) {
img2num::threshold_image(out_image.mutable_data(), width, height, num_thresholds);
return out_image;
},
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("num_thresholds"),
"Apply thresholding to the image");
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"),
pybind11::arg("num_thresholds"), "Apply thresholding to the image");

m.def(
"black_threshold_image",
Expand All @@ -62,8 +62,8 @@ PYBIND11_MODULE(_img2num, m) {
img2num::black_threshold_image(out_image.mutable_data(), width, height, num_thresholds);
return out_image;
},
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("num_thresholds"),
"Apply black thresholding to the image");
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"),
pybind11::arg("num_thresholds"), "Apply black thresholding to the image");

m.def(
"bilateral_filter",
Expand All @@ -74,17 +74,17 @@ PYBIND11_MODULE(_img2num, m) {
std::memcpy(out_image.mutable_data(), buf.ptr, buf.size * sizeof(uint8_t));

img2num::bilateral_filter(out_image.mutable_data(), width, height, sigma_spatial,
sigma_range, color_space);
sigma_range, color_space);
return out_image;
},
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("sigma_spatial"),
pybind11::arg("sigma_range"), pybind11::arg("color_space"),
pybind11::arg("image"), pybind11::arg("width"), pybind11::arg("height"),
pybind11::arg("sigma_spatial"), pybind11::arg("sigma_range"), pybind11::arg("color_space"),
"Apply bilateral filter");

m.def(
"kmeans",
[](pybind11::array_t<uint8_t, pybind11::array::c_style> data, int32_t width, int32_t height, int32_t k,
int32_t max_iter, uint8_t color_space) {
[](pybind11::array_t<uint8_t, pybind11::array::c_style> data, int32_t width, int32_t height,
int32_t k, int32_t max_iter, uint8_t color_space) {
pybind11::buffer_info data_buf = data.request();

// Allocate NumPy arrays for the outputs
Expand All @@ -96,28 +96,28 @@ PYBIND11_MODULE(_img2num, m) {

// Call C function
img2num::kmeans(static_cast<const uint8_t*>(data_buf.ptr), out_data_ptr, out_labels_ptr,
width, height, k, max_iter, color_space);
width, height, k, max_iter, color_space);

// Return a tuple of (out_data, out_labels)
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"),
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)");

m.def(
"labels_to_svg",
[](pybind11::array_t<uint8_t, pybind11::array::c_style> data,
pybind11::array_t<int32_t, pybind11::array::c_style> labels, int width, int height, int min_area) {

pybind11::array_t<int32_t, pybind11::array::c_style> labels, int width, int height,
int min_area) {
const uint8_t* data_ptr{static_cast<const uint8_t*>(data.request().ptr)};
const int32_t* labels_ptr{static_cast<const int32_t*>(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;
},
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"), "Convert labels to SVG string");
}
4 changes: 2 additions & 2 deletions core/include/img2num.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ void bilateral_filter(uint8_t *image, size_t width, size_t height, double sigma_
double sigma_range, uint8_t color_space);

/// @copydoc IMG2NUM_H_LABELS_TO_SVG_DOC
std::string labels_to_svg(const uint8_t *data, const int32_t *labels, const int width, const int height,
const int min_area);
std::string labels_to_svg(const uint8_t *data, const int32_t *labels, const int width,
const int height, const int min_area);
} // namespace img2num

#endif // IMG2NUM_H
4 changes: 2 additions & 2 deletions core/src/internal/labels_to_svg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ format ([r,g,b,a, r,g,b,a, ...]) labels: int32_t* -> output of labelled regions
from K-Means, should be 1/4 the size of data since data is RGBA labels : width *
height : number of pixels in image = 1 : 1 : 1
*/
std::string labels_to_svg(const uint8_t *data, const int32_t *labels, const int width, const int height,
const int min_area) {
std::string labels_to_svg(const uint8_t *data, const int32_t *labels, const int width,
const int height, const int min_area) {
const int32_t num_pixels{width * height};
std::vector<int32_t> labels_vector{labels, labels + num_pixels};
std::vector<int32_t> region_labels;
Expand Down
2 changes: 1 addition & 1 deletion docs/blog/2025-12-05-launch.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tags: [launch, tutorial]

We are excited to launch **Img2Num**, the interactive app that converts any image into a color-by-number template.

<!-- truncate -->
{/* truncate */}

Try it out online at [https://ryan-millard.github.io/Img2Num/](https://ryan-millard.github.io/Img2Num/) and start coloring your favorite images today!

Expand Down
23 changes: 16 additions & 7 deletions docs/docs/c/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,25 @@ description: >
for easier navigation and code browsing.
---

import FullscreenIframe from '@site/src/components/FullscreenIframe';
import FullscreenIframe from "@site/src/components/FullscreenIframe";

export const DocsLink = () => (
<a
href="/Img2Num/info/docs/c/api/"
onClick={(e) => {
e.preventDefault();
window.location.href = "/Img2Num/info/docs/c/api/";
}}
>
{" "}
Doxygen documentation{" "}
</a>
);

> Don't like iframes?
> Visit the{' '}
> <a href="/Img2Num/info/docs/c/api/" onClick={(e) => { e.preventDefault(); window.location.href = "/Img2Num/info/docs/c/api/"; }}> Doxygen documentation </a>{' '} directly.
> Visit the{' '} <DocsLink /> directly.

<FullscreenIframe
src="/Img2Num/info/docs/c/api/"
title="C API Reference (Doxygen)"
/>
<FullscreenIframe src="/Img2Num/info/docs/c/api/" title="C API Reference (Doxygen)" />

## About this page

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/c/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Docs

import Hedgehog from '@site/src/components/Hedgehog';
import Hedgehog from "@site/src/components/Hedgehog";

:::danger Help Wanted!
We need help with writing manual docs.
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/c/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ sidebar_label: C
sidebar_position: 3
---

<!--DO NOT CHANGE THE TITLE (see @site/src/md/_partials/IntsallingCoreOrCFromSrc.md and the C++ version of this page to understand why-->
{/* DO NOT CHANGE THE TITLE (see @site/src/md/_partials/IntsallingCoreOrCFromSrc.md and the C++ version of this page to understand why */}

import Features from '@site/src/md/\_partials/library-features.md';
import Features from "@site/src/md/\_partials/library-features.md";

<Features />

import InstallingCoreOrCFromSrc from '@site/src/md/\_partials/IntsallingCoreOrCFromSrc.md';
import InstallingCoreOrCFromSrc from "@site/src/md/\_partials/IntsallingCoreOrCFromSrc.md";

<InstallingCoreOrCFromSrc />
44 changes: 18 additions & 26 deletions docs/docs/contributing/setup-and-dependencies/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ sidebar_label: 🛠️ Setup & Dependencies
sidebar_position: 1
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

## Prerequisites

Expand Down Expand Up @@ -67,12 +67,14 @@ values={[
</Tabs>

:::info About the `img2num` script

It is a thin wrapper around Docker and pnpm that allows you to conveniently run scripts inside the Docker environment.

> See [img2num](https://github.com/Ryan-Millard/Img2Num/blob/main/example-apps/react-js/src/components/WasmImageProcessor.jsx),
> [img2num.ps1](https://github.com/Ryan-Millard/Img2Num/blob/main/img2num.ps1),
> and [img2num.bat](https://github.com/Ryan-Millard/Img2Num/blob/main/img2num.bat).
> :::

:::

### Using the Docker wrapper script

Expand Down Expand Up @@ -115,27 +117,16 @@ In future docs, assume that the commands are to be run in the Docker terminal.

- `./img2num pnpm <args>` is a proxy to pnpm inside the Docker container's shell.
<Tabs
defaultValue="root"
values={[
{ label: 'Root', value: 'root' },
{ label: 'Docs', value: 'docs' },
{ label: 'React Example App', value: 'react-example' },
]}>
<TabItem value="root">
`bash title="Fuzzy find scripts local to the root project"
./img2num pnpm run help
`
</TabItem>
<TabItem value="docs">
`bash title="Fuzzy find scripts local to the documentation"
./img2num pnpm run -F docs help
`
</TabItem>
<TabItem value="react-example">
`bash title="Fuzzy find scripts local to the React Example app"
./img2num pnpm run -F react-example help
`
</TabItem>
defaultValue="root"
values={[
{ label: "Root", value: "root" },
{ label: "Docs", value: "docs" },
{ label: "React Example App", value: "react-example" },
]}
>
<TabItem value="root">`bash title="Fuzzy find scripts local to the root project" ./img2num pnpm run help `</TabItem>
<TabItem value="docs">`bash title="Fuzzy find scripts local to the documentation" ./img2num pnpm run -F docs help `</TabItem>
<TabItem value="react-example">`bash title="Fuzzy find scripts local to the React Example app" ./img2num pnpm run -F react-example help `</TabItem>
</Tabs>
- `./img2num sh`, `./img2num shell`, and `./img2num bash` all open the Docker container's interactive terminal.

Expand Down Expand Up @@ -191,8 +182,9 @@ cmake --install build
:::info JavaScript Prerequisite
Excluding the documentation and CLI scripts, compiling the library to WASM is required before using the JavaScript library.

> The example apps depend on the library, so they will also fail if you have not compiled the WASM.
> :::
The example apps depend on the library, so they will also fail if you have not compiled the WASM.

:::

This compiles the core C++ image processing library to WebAssembly using Emscripten.

Expand Down
23 changes: 16 additions & 7 deletions docs/docs/cpp/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,25 @@ description: >
for easier navigation and code browsing.
---

import FullscreenIframe from '@site/src/components/FullscreenIframe';
import FullscreenIframe from "@site/src/components/FullscreenIframe";

export const DocsLink = () => (
<a
href="/Img2Num/info/docs/cpp/api/"
onClick={(e) => {
e.preventDefault();
window.location.href = "/Img2Num/info/docs/cpp/api/";
}}
>
{" "}
Doxygen documentation{" "}
</a>
);

> Don't like iframes?
> Visit the{' '}
> <a href="/Img2Num/info/docs/cpp/api/" onClick={(e) => { e.preventDefault(); window.location.href = "/Img2Num/info/docs/cpp/api/"; }}> Doxygen documentation </a>{' '} directly.
> Visit the{' '} <DocsLink /> directly.

<FullscreenIframe
src="/Img2Num/info/docs/cpp/api/"
title="C++ API Reference (Doxygen)"
/>
<FullscreenIframe src="/Img2Num/info/docs/cpp/api/" title="C++ API Reference (Doxygen)" />

## About this page

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/cpp/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Docs

import Hedgehog from '@site/src/components/Hedgehog';
import Hedgehog from "@site/src/components/Hedgehog";

:::danger Help Wanted!
We need help with writing manual docs.
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/cpp/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ sidebar_label: C++
sidebar_position: 2
---

<!--DO NOT CHANGE THE TITLE (see @site/src/md/_partials/IntsallingCoreOrCFromSrc.md and the C version of this page to understand why-->
{/* DO NOT CHANGE THE TITLE (see @site/src/md/_partials/IntsallingCoreOrCFromSrc.md and the C version of this page to understand why */}

import Features from '@site/src/md/\_partials/library-features.md';
import Features from "@site/src/md/\_partials/library-features.md";

<Features />

import InstallingCoreOrCFromSrc from '@site/src/md/\_partials/IntsallingCoreOrCFromSrc.md';
import InstallingCoreOrCFromSrc from "@site/src/md/\_partials/IntsallingCoreOrCFromSrc.md";

<InstallingCoreOrCFromSrc />
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ The application needs to be compiled beforehand, so make sure to follow the inst
Once built, you can run the applications as shown below.
:::

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

<Tabs defaultValue="cpp">
<TabItem value="cpp" label="C++ console app">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebar_position: 2

Defined inside `:root.dark { ... }` in `/src/global-styles/variables.css`.

import ColorSwatch from '@site/src/components/ColorSwatch';
import ColorSwatch from "@site/src/components/ColorSwatch";

## Colors — Dark mode (Deep Forest Night)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebar_position: 1

Defined inside `:root.light { ... }` in `/src/global-styles/variables.css`.

import ColorSwatch from '@site/src/components/ColorSwatch';
import ColorSwatch from "@site/src/components/ColorSwatch";

## Colors — Light mode (Warm Hedgehog Palette)

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/internal/packages/js/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ All data is copied between JavaScript and WASM - this avoids unexpected use-afte

### Key responsibilities

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

<Tabs groupId="wasm-worker" defaultValue="flow">
<TabItem value="flow" label="Flow diagram">
Expand Down
Loading
Loading