Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
4d97303
testing axios with http
kalwalt Mar 12, 2022
cc0eb6f
new artoolkitNFT_node_wasm.js
kalwalt Mar 12, 2022
b49f70a
simplified node lib
kalwalt Mar 12, 2022
ff6d8e6
new ARToolkitNFT.js for nodejs
kalwalt Mar 13, 2022
60011da
loadCamera method
kalwalt Mar 13, 2022
916a1ca
testing loadCamera
kalwalt Mar 13, 2022
cb163cf
another test
kalwalt Mar 22, 2022
1662e2c
trying to load the Camera
kalwalt Mar 29, 2022
b7f37f5
loadCamera run without errors
kalwalt Apr 1, 2022
ba13069
fix for https://github.com/webarkit/jsartoolkitNFT/issues/129
kalwalt Apr 1, 2022
118c1a0
new ARControllerNFT for node
kalwalt Apr 1, 2022
91ffe91
starting to add loadNFTMarker
kalwalt Apr 15, 2022
0b3dd5e
now it load a single NFT marker!!
kalwalt Apr 16, 2022
dd4fe63
simple example with sharp
kalwalt Apr 16, 2022
f2ad354
testing new getNFTMarker function
kalwalt Apr 28, 2022
5c37fae
testng new node listeners
kalwalt Jun 29, 2022
5bada1e
testing another image format
kalwalt Oct 31, 2022
6322d72
getNFTData function
kalwalt Oct 31, 2022
58d6a3d
getCameraMatrix function
kalwalt Oct 31, 2022
4db6c37
maybe th image format is not correct?
kalwalt Oct 31, 2022
21ee6b7
Merge branch 'dev' into feature-node-libs
kalwalt Feb 22, 2023
ad4a66b
rebuilding libs and small improves
kalwalt Feb 22, 2023
5dd5cf2
Merge branch 'dev' into feature-node-libs
kalwalt Apr 3, 2023
9ca6a29
rebuilding libs after merging
kalwalt Apr 3, 2023
fb9854e
installing packages
kalwalt Apr 4, 2023
95c583e
Merge branch 'master' into feature-node-libs
kalwalt Oct 26, 2024
b555171
rebuildiing libs and improves to node example.js
kalwalt Nov 7, 2024
6b3cc8d
new distribution file (ARToolkitNFT_node.js) for node env, under test…
kalwalt Feb 18, 2025
5723b2a
Add new canvas example and update ARToolkitNFT methods for improved m…
kalwalt Feb 19, 2025
24bdc8c
Add IARToolkitNFT_node interface and update ARToolkitNFT class method…
kalwalt Feb 19, 2025
8ce8d67
Add requestAnimationFrame polyfill and refactor image processing in e…
kalwalt Mar 9, 2025
74d561c
Merge branch 'dev'
kalwalt May 3, 2026
df8ceb5
Merge branch 'dev'
kalwalt May 27, 2026
409b7da
Fix NFT marker detection in node examples
kalwalt May 28, 2026
f2618df
Sync .gitignore from master
kalwalt May 28, 2026
4274fcd
Use pinball-demo.jpg and 2000x1500 in canvas example
kalwalt May 28, 2026
f86a9fe
Merge branch 'master' into feature-node-libs
kalwalt May 28, 2026
909b9a7
Add node types to tsconfig and rebuild node lib
kalwalt May 28, 2026
fc75bc2
Remove unused test images and ignore zlib build dir
kalwalt May 28, 2026
a37476b
Use commonjs2 for node webpack target
kalwalt May 28, 2026
4e319d9
Add exports map with node/browser conditions and named subpaths
kalwalt May 28, 2026
5e7169b
Document exports map and named subpaths in README
kalwalt May 28, 2026
b4787bc
Remove node-src in favor of the dist node build
kalwalt May 28, 2026
fd7355e
Document experimental Node.js usage in README
kalwalt May 28, 2026
ab4468d
Clean up node example console output and fix getNFTMarker event
kalwalt May 28, 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build/*.a
node_modules
docs/*
emscripten/build
emscripten/zlib/build
python-bindings/build
python-bindings/dist
python-bindings/emscripten
Expand Down
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,34 @@ then:
import { ARToolkitNFT, ARControllerNFT } from '@webarkit/jsartoolkit-nft'
```

The package ships an [`exports`](https://nodejs.org/api/packages.html#package-entry-points) map, so the right build is picked automatically per environment:

- in a **browser / bundler**, `@webarkit/jsartoolkit-nft` resolves to the UMD build (`dist/ARToolkitNFT.js`);
- in **Node.js**, it resolves to the Node build (`dist/ARToolkitNFT_node.js`, CommonJS).

```javascript
// browser / bundler -> UMD build
import { ARToolkitNFT, ARControllerNFT } from '@webarkit/jsartoolkit-nft'

// Node.js -> Node build
const { ARToolkitNFT, ARControllerNFT } = require('@webarkit/jsartoolkit-nft')
```

You can also target a specific build through a named subpath:

| Import | Build |
| --- | --- |
| `@webarkit/jsartoolkit-nft` | UMD (browser) / Node (Node.js) |
| `@webarkit/jsartoolkit-nft/simd` | SIMD WASM build |
| `@webarkit/jsartoolkit-nft/td` | threaded (pthread) build |
| `@webarkit/jsartoolkit-nft/node` | Node build |

```javascript
import '@webarkit/jsartoolkit-nft/simd'
```

The raw `dist/*` deep-imports (e.g. `@webarkit/jsartoolkit-nft/dist/ARToolkitNFT_simd.js`) still work, and `<script>` / `importScripts` URLs are not affected by the `exports` map. In Node the build is CommonJS, so use `require()` or a default `import` (named `import { ... }` will come with a future ESM build).

**Note**: All the examples in the repository are running the code inside a Worker (don't use it in the main thread!). So i you need to import the library in a worker you need to use the `importScripts` function.

```javascript
Expand Down Expand Up @@ -169,6 +197,65 @@ The Python bindings are built and tested on **Linux**, **macOS** and **Windows**

For full build-from-source instructions, local development tips and the TestPyPI publishing workflow, see [`python-bindings/README.md`](python-bindings/README.md).

## Node.js 🟢 (experimental)

❕❕❕ ATTENTION: Node.js support is experimental and under active development. The API may change without notice and it is not yet recommended for production use.

**JSARToolKitNFT** ships a dedicated Node.js build (`dist/ARToolkitNFT_node.js`), compiled from the same TypeScript sources and WebARKitLib C/C++ core as the browser build. It lets you run NFT marker detection server-side on static image data, without a browser, camera or `<canvas>`.

When you install the package, Node automatically resolves to this build (see the [`exports`](#using-the-library-) map):

```javascript
// CommonJS — resolves to the Node build in Node.js
const { ARControllerNFT } = require('@webarkit/jsartoolkit-nft');
// or the explicit subpath
const { ARControllerNFT } = require('@webarkit/jsartoolkit-nft/node');
```

A minimal example decoding an image with [sharp](https://github.com/lovell/sharp) and feeding the RGBA pixels to the controller:

```javascript
const { ARControllerNFT } = require('@webarkit/jsartoolkit-nft');
const sharp = require('sharp');

async function init() {
const arControllerNFT = await new ARControllerNFT(2000, 1500, '/camera_para.dat');
const ar = await arControllerNFT._initialize();

// process() expects RGBA pixel data, so add the alpha channel.
const data = await sharp('pinball-demo.jpg').ensureAlpha().raw().toBuffer();
const imageData = new Uint8Array(data.buffer);

ar.on('getNFTMarker', (e) => console.log('NFT marker detected: ', e));

ar.loadNFTMarker('DataNFT/pinball', (id) => {
ar.trackNFTMarkerId(id);
// NFT tracking needs several iterations before it locks on.
for (let i = 0; i < 10; i++) ar.process(imageData);
});
}

init();
```

### What works

- Loading NFT marker datasets (`.fset`, `.fset3`, `.iset`)
- KPM-based marker detection and AR2 tracking with pose matrix output
- Event listener for `getNFTMarker`
- Decoding image input via [sharp](https://github.com/lovell/sharp) or the [canvas](https://github.com/Automattic/node-canvas) package (`process()` expects **RGBA** pixel data)

### Not yet implemented

- Native ESM consumption (`import { ARControllerNFT } from ...`): the Node build is CommonJS for now, so use `require()` or a default `import`
- Live camera capture (the examples process a single static image)

Runnable examples live in [`examples/node`](examples/node): [`example_dist.js`](examples/node/example_dist.js) (sharp + the Node build) and [`example_canvas.js`](examples/node/example_canvas.js) (the [canvas](https://github.com/Automattic/node-canvas) package). Run one with:

```bash
cd examples/node && node example_dist.js
```

## Project Structure 📂

- `build/` (compiled debug and minified versions of JSARToolKitNFT)
Expand Down
2 changes: 1 addition & 1 deletion build/artoolkitNFT.debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
this._src = "";
this.complete = false;
};
// ARToolKit exported JS API
// ARToolKitNFT exported JS API
const artoolkitNFT = {
UNKNOWN_MARKER: -1,
NFT_MARKER: 0,
Expand Down
1 change: 1 addition & 0 deletions build/artoolkitNFT_node_wasm.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/ARToolkitNFT_node.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/ARToolkitNFT_node.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
Binary file added examples/node/DataNFT/pinball.fset
Binary file not shown.
Binary file added examples/node/DataNFT/pinball.fset3
Binary file not shown.
Binary file added examples/node/DataNFT/pinball.iset
Binary file not shown.
Binary file added examples/node/camera_para.dat
Binary file not shown.
76 changes: 76 additions & 0 deletions examples/node/example_build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const Module = require('../../build/artoolkitNFT_node_wasm.js');

console.log('This is a test importing artoolkitNFT_node_wasm with Nodejs')

var scope;
if (typeof global !== 'undefined') {
scope = global;
} else {
scope = self;
}

// ARToolKitNFT exported JS API
//
var artoolkitNFT = {

UNKNOWN_MARKER: -1,
NFT_MARKER: 0, // 0,

};

var FUNCTIONS = [
'setup',
'teardown',

'setupAR2',

'setLogLevel',
'getLogLevel',

'setDebugMode',
'getDebugMode',

'getProcessingImage',

'detectMarker',
'detectNFTMarker',
'getNFTMarker',
'getNFTData',

'setProjectionNearPlane',
'getProjectionNearPlane',

'setProjectionFarPlane',
'getProjectionFarPlane',

'setThresholdMode',
'getThresholdMode',

'setThreshold',
'getThreshold',

'setImageProcMode',
'getImageProcMode',
];

function runWhenLoaded() {
FUNCTIONS.forEach(function (n) {
artoolkitNFT[n] = Module[n];
});

for (var m in Module) {
if (m.match(/^AR/))
artoolkitNFT[m] = Module[m];
}
}

/* Exports */
scope.artoolkitNFT = artoolkitNFT;

Module.onRuntimeInitialized = async function () {
runWhenLoaded();

console.log(artoolkitNFT);

artoolkitNFT.setup(640, 480, 0);
}
54 changes: 54 additions & 0 deletions examples/node/example_canvas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const jsartoolkitNFT = require ('../../dist/ARToolkitNFT_node.js');
const { createCanvas, loadImage } = require('canvas');
const fs = require('fs');

// Polyfill for requestAnimationFrame in Node.js
global.requestAnimationFrame = function(callback) {
return setImmediate(callback);
};

global.cancelAnimationFrame = function(id) {
clearImmediate(id);
};

async function init() {
console.log(__dirname + '/camera_para.dat');

let arControllerNFT = new jsartoolkitNFT.ARControllerNFT(2000, 1500, '/camera_para.dat');
let ar = await arControllerNFT._initialize();
loadImage('pinball-demo.jpg').then((image) => {

console.log('image: ', image.width, image.height);
const canvas = createCanvas(image.width, image.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, image.width, image.height);
const imgData = ctx.getImageData(0, 0, image.width, image.height);
ar.on('getNFTMarker', function(e){
console.log("NFT marker detected: ", e.data.marker);
});
const cameraMatrix = ar.getCameraMatrix();
ar.loadNFTMarker('DataNFT/pinball', function (id) {
console.log('marker id is: ', id);
ar.trackNFTMarkerId(id);
let marker = ar.getNFTData(id, 0);
console.log("cameraMatrix: ", cameraMatrix);
});

function processFrame() {
if (ar && typeof ar.process === 'function') {
ar.process(imgData.data);
}
requestAnimationFrame(processFrame);
}

processFrame();

// Save the canvas to a PNG file
const out = fs.createWriteStream(__dirname + '/output.png');
const stream = canvas.createPNGStream();
stream.pipe(out);
out.on('finish', () => console.log('The PNG file was created.'));
});
}

init();
31 changes: 31 additions & 0 deletions examples/node/example_dist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const jsartoolkitNFT = require('../../dist/ARToolkitNFT_node.js')
const sharp = require('sharp')

async function init() {
const arControllerNFT = await new jsartoolkitNFT.ARControllerNFT(2000, 1500, '/camera_para.dat');
const ar = await arControllerNFT._initialize();

// process() expects RGBA pixel data, so add the alpha channel.
const data = await sharp("pinball-demo.jpg").ensureAlpha().raw().toBuffer();
const imageData = new Uint8Array(data.buffer);

ar.on('getNFTMarker', function (e) {
console.log("NFT marker detected: ", e.data.marker);
});

const cameraMatrix = ar.getCameraMatrix();
ar.loadNFTMarker('DataNFT/pinball', function (id) {
console.log('marker id is: ', id);
ar.trackNFTMarkerId(id);
const marker = ar.getNFTData(ar.id, 0);
console.log("nftMarker data: ", marker);
console.log("cameraMatrix: ", cameraMatrix);
// process() must run after the marker is loaded; NFT tracking
// needs several iterations before it locks on.
for (let i = 0; i < 10; i++) {
ar.process(imageData);
}
});
}

init()
Binary file added examples/node/output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/node/pinball-demo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/node/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node example_build.js
10 changes: 10 additions & 0 deletions examples/node/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const fs = require("fs");

let data = fs.readFileSync('../Data/camera_para.dat', {encoding: 'binary'},function(err){
console.log(error);
})
console.log('data is: ', data);

fs.readFile('../Data/camera_para.dat', {encoding: 'binary'}, function (err, data) {
console.log(data);
})
2 changes: 1 addition & 1 deletion js/artoolkitNFT.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@



// ARToolKit exported JS API
// ARToolKitNFT exported JS API
//
const artoolkitNFT = {

Expand Down
Loading
Loading