@thi.ng/geom-trace-bitmap 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -1
- package/README.md +14 -1
- package/api.d.ts +17 -7
- package/extract.d.ts +12 -4
- package/extract.js +13 -2
- package/package.json +10 -10
- package/trace.d.ts +2 -2
- package/trace.js +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-
|
|
3
|
+
- **Last updated**: 2023-04-08T11:09:50Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,17 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [0.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-trace-bitmap@0.3.0) (2023-04-08)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add TraceOpts.max ([3b39d61](https://github.com/thi-ng/umbrella/commit/3b39d61))
|
|
17
|
+
- update TraceOpts.select() ([01b9e49](https://github.com/thi-ng/umbrella/commit/01b9e49))
|
|
18
|
+
- add point coords as 2nd select() arg
|
|
19
|
+
- update extractSegmentX/Y() ([274f71d](https://github.com/thi-ng/umbrella/commit/274f71d))
|
|
20
|
+
- update result to include unmatched points
|
|
21
|
+
- update tests
|
|
22
|
+
|
|
12
23
|
## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/geom-trace-bitmap@0.2.0) (2023-03-25)
|
|
13
24
|
|
|
14
25
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ This project is part of the
|
|
|
14
14
|
- [Related packages](#related-packages)
|
|
15
15
|
- [Installation](#installation)
|
|
16
16
|
- [Dependencies](#dependencies)
|
|
17
|
+
- [Usage examples](#usage-examples)
|
|
17
18
|
- [API](#api)
|
|
18
19
|
- [Basic usage](#basic-usage)
|
|
19
20
|
- [Authors](#authors)
|
|
@@ -65,7 +66,7 @@ For Node.js REPL:
|
|
|
65
66
|
const geomTraceBitmap = await import("@thi.ng/geom-trace-bitmap");
|
|
66
67
|
```
|
|
67
68
|
|
|
68
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
69
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 988 bytes
|
|
69
70
|
|
|
70
71
|
## Dependencies
|
|
71
72
|
|
|
@@ -76,6 +77,18 @@ Package sizes (brotli'd, pre-treeshake): ESM: 940 bytes
|
|
|
76
77
|
- [@thi.ng/pixel](https://github.com/thi-ng/umbrella/tree/develop/packages/pixel)
|
|
77
78
|
- [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/develop/packages/vectors)
|
|
78
79
|
|
|
80
|
+
## Usage examples
|
|
81
|
+
|
|
82
|
+
Several demos in this repo's
|
|
83
|
+
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples)
|
|
84
|
+
directory are using this package.
|
|
85
|
+
|
|
86
|
+
A selection:
|
|
87
|
+
|
|
88
|
+
| Screenshot | Description | Live demo | Source |
|
|
89
|
+
|:--------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------|:---------------------------------------------------|:--------------------------------------------------------------------------------|
|
|
90
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/trace-bitmap.jpg" width="240"/> | Multi-layer vectorization & dithering of bitmap images | [Demo](https://demo.thi.ng/umbrella/trace-bitmap/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/trace-bitmap) |
|
|
91
|
+
|
|
79
92
|
## API
|
|
80
93
|
|
|
81
94
|
[Generated API docs](https://docs.thi.ng/umbrella/geom-trace-bitmap/)
|
package/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { FnU2, Predicate } from "@thi.ng/api";
|
|
2
|
-
import type { GridIterator2D,
|
|
1
|
+
import type { Fn2, FnU2, Predicate } from "@thi.ng/api";
|
|
2
|
+
import type { GridCoord2D, GridIterator2D, PointTransform2D } from "@thi.ng/grid-iterators";
|
|
3
3
|
import type { ReadonlyMat } from "@thi.ng/matrices";
|
|
4
4
|
import type { IntBuffer } from "@thi.ng/pixel";
|
|
5
5
|
export interface TraceOpts {
|
|
@@ -12,16 +12,26 @@ export interface TraceOpts {
|
|
|
12
12
|
*/
|
|
13
13
|
img: IntBuffer;
|
|
14
14
|
/**
|
|
15
|
-
* Predicate function to determine if a pixel
|
|
16
|
-
* line.
|
|
15
|
+
* Predicate function to determine if a pixel position (or pixel value) is
|
|
16
|
+
* considered selectable (part of a line or point cloud). The function is
|
|
17
|
+
* being called with the pixel value and its coordinates.
|
|
18
|
+
*
|
|
19
|
+
* @param val
|
|
20
|
+
* @param p
|
|
17
21
|
*/
|
|
18
|
-
select:
|
|
22
|
+
select: Fn2<number, GridCoord2D, boolean>;
|
|
19
23
|
/**
|
|
20
|
-
* Minimum length of line segments (in pixels).
|
|
24
|
+
* Minimum length of line segments (in consecutive pixels).
|
|
21
25
|
*
|
|
22
26
|
* @defaultValue 2
|
|
23
27
|
*/
|
|
24
28
|
min?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Maximum length of line segments (in consecutive pixels).
|
|
31
|
+
*
|
|
32
|
+
* @defaultValue Infinity
|
|
33
|
+
*/
|
|
34
|
+
max?: number;
|
|
25
35
|
/**
|
|
26
36
|
* Clear value to replace extracted pixels with.
|
|
27
37
|
*
|
|
@@ -80,7 +90,7 @@ export interface TraceDirImpl {
|
|
|
80
90
|
* Optional point transform passed to {@link TraceDirImpl.order} (e.g. to
|
|
81
91
|
* flip iteration order and therefore line direction)
|
|
82
92
|
*/
|
|
83
|
-
tx?:
|
|
93
|
+
tx?: PointTransform2D;
|
|
84
94
|
}
|
|
85
95
|
export type BorderFn = FnU2<number, Predicate<[number, number]>>;
|
|
86
96
|
//# sourceMappingURL=api.d.ts.map
|
package/extract.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import type { ReadonlyVec, VecPair } from "@thi.ng/vectors";
|
|
1
|
+
import type { ReadonlyVec, Vec, VecPair } from "@thi.ng/vectors";
|
|
2
2
|
/**
|
|
3
3
|
* Extracts horizontal line segments (along X-axis) from given point cloud
|
|
4
|
-
* (assuming all points are aligned to a grid, e.g. pixel coords).
|
|
4
|
+
* (assuming all points are aligned to a grid, e.g. pixel coords). Returns
|
|
5
|
+
* object of `{segments, points}`, where `segments` contains all extracted
|
|
6
|
+
* segments and `points` all remaining/unmatched points.
|
|
5
7
|
*
|
|
6
8
|
* @remarks
|
|
7
9
|
* The given point array will be sorted (in-place!). Line segments will be as
|
|
@@ -14,7 +16,10 @@ import type { ReadonlyVec, VecPair } from "@thi.ng/vectors";
|
|
|
14
16
|
* @param pts
|
|
15
17
|
* @param maxDist
|
|
16
18
|
*/
|
|
17
|
-
export declare const extractSegmentsX: (pts: ReadonlyVec[], maxD?: number) =>
|
|
19
|
+
export declare const extractSegmentsX: (pts: ReadonlyVec[], maxD?: number) => {
|
|
20
|
+
segments: VecPair[];
|
|
21
|
+
points: Vec[];
|
|
22
|
+
};
|
|
18
23
|
/**
|
|
19
24
|
* Similar to {@link extractSegmentsX}, but for extracting vertical line
|
|
20
25
|
* segments (along Y-axis).
|
|
@@ -22,5 +27,8 @@ export declare const extractSegmentsX: (pts: ReadonlyVec[], maxD?: number) => Ve
|
|
|
22
27
|
* @param pts
|
|
23
28
|
* @param maxDist
|
|
24
29
|
*/
|
|
25
|
-
export declare const extractSegmentsY: (pts: ReadonlyVec[], maxDist?: number) =>
|
|
30
|
+
export declare const extractSegmentsY: (pts: ReadonlyVec[], maxDist?: number) => {
|
|
31
|
+
segments: VecPair[];
|
|
32
|
+
points: Vec[];
|
|
33
|
+
};
|
|
26
34
|
//# sourceMappingURL=extract.d.ts.map
|
package/extract.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { comparator2 } from "@thi.ng/vectors/compare";
|
|
2
2
|
/**
|
|
3
3
|
* Extracts horizontal line segments (along X-axis) from given point cloud
|
|
4
|
-
* (assuming all points are aligned to a grid, e.g. pixel coords).
|
|
4
|
+
* (assuming all points are aligned to a grid, e.g. pixel coords). Returns
|
|
5
|
+
* object of `{segments, points}`, where `segments` contains all extracted
|
|
6
|
+
* segments and `points` all remaining/unmatched points.
|
|
5
7
|
*
|
|
6
8
|
* @remarks
|
|
7
9
|
* The given point array will be sorted (in-place!). Line segments will be as
|
|
@@ -33,9 +35,12 @@ export const extractSegmentsY = (pts, maxDist = 5) => __extract(pts, maxDist, 0)
|
|
|
33
35
|
* @internal
|
|
34
36
|
*/
|
|
35
37
|
const __extract = (pts, maxD, order) => {
|
|
38
|
+
if (pts.length < 2)
|
|
39
|
+
return { segments: [], points: pts };
|
|
36
40
|
const $ = order ? (p) => [p[1], p[0]] : (p) => p;
|
|
37
41
|
pts = pts.sort(comparator2(order, order ^ 1));
|
|
38
42
|
const segments = [];
|
|
43
|
+
const points = [];
|
|
39
44
|
let [outer, inner] = $(pts[0]);
|
|
40
45
|
let last = 0;
|
|
41
46
|
for (let i = 1, n = pts.length - 1; i <= n; i++) {
|
|
@@ -45,6 +50,9 @@ const __extract = (pts, maxD, order) => {
|
|
|
45
50
|
if (i - last > 1) {
|
|
46
51
|
segments.push([pts[last], pts[i - 1]]);
|
|
47
52
|
}
|
|
53
|
+
else {
|
|
54
|
+
points.push(pts[last]);
|
|
55
|
+
}
|
|
48
56
|
last = i;
|
|
49
57
|
}
|
|
50
58
|
inner = p[1];
|
|
@@ -53,9 +61,12 @@ const __extract = (pts, maxD, order) => {
|
|
|
53
61
|
if (i - last > 1) {
|
|
54
62
|
segments.push([pts[last], pts[i - 1]]);
|
|
55
63
|
}
|
|
64
|
+
else {
|
|
65
|
+
points.push(pts[last]);
|
|
66
|
+
}
|
|
56
67
|
last = i;
|
|
57
68
|
[outer, inner] = p;
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
|
-
return segments;
|
|
71
|
+
return { segments, points };
|
|
61
72
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/geom-trace-bitmap",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Bitmap image to hairline vector and point cloud conversions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -34,20 +34,20 @@
|
|
|
34
34
|
"test": "testament test"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@thi.ng/api": "^8.
|
|
38
|
-
"@thi.ng/errors": "^2.2.
|
|
39
|
-
"@thi.ng/grid-iterators": "^
|
|
40
|
-
"@thi.ng/matrices": "^2.1.
|
|
41
|
-
"@thi.ng/pixel": "^4.1
|
|
42
|
-
"@thi.ng/vectors": "^7.6.
|
|
37
|
+
"@thi.ng/api": "^8.8.0",
|
|
38
|
+
"@thi.ng/errors": "^2.2.15",
|
|
39
|
+
"@thi.ng/grid-iterators": "^4.0.1",
|
|
40
|
+
"@thi.ng/matrices": "^2.1.53",
|
|
41
|
+
"@thi.ng/pixel": "^4.2.1",
|
|
42
|
+
"@thi.ng/vectors": "^7.6.12"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@microsoft/api-extractor": "^7.34.4",
|
|
46
|
-
"@thi.ng/testament": "^0.3.
|
|
46
|
+
"@thi.ng/testament": "^0.3.15",
|
|
47
47
|
"rimraf": "^4.4.1",
|
|
48
48
|
"tools": "^0.0.1",
|
|
49
49
|
"typedoc": "^0.23.28",
|
|
50
|
-
"typescript": "^5.0.
|
|
50
|
+
"typescript": "^5.0.4"
|
|
51
51
|
},
|
|
52
52
|
"keywords": [
|
|
53
53
|
"bitmap",
|
|
@@ -100,5 +100,5 @@
|
|
|
100
100
|
"status": "alpha",
|
|
101
101
|
"year": 2022
|
|
102
102
|
},
|
|
103
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "3a56bc490f1e68754762a503d06327b5b34ff7eb\n"
|
|
104
104
|
}
|
package/trace.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Fn, Predicate } from "@thi.ng/api";
|
|
2
|
-
import type {
|
|
2
|
+
import type { GridIterOpts2D, PointTransform2D } from "@thi.ng/grid-iterators";
|
|
3
3
|
import type { Vec, VecPair } from "@thi.ng/vectors";
|
|
4
4
|
import type { TraceBitmapOpts, TraceOpts } from "./api.js";
|
|
5
5
|
/**
|
|
@@ -30,7 +30,7 @@ export declare const traceBitmap: (opts: TraceBitmapOpts) => {
|
|
|
30
30
|
* @param tx
|
|
31
31
|
* @param acc
|
|
32
32
|
*/
|
|
33
|
-
export declare const traceLines: (opts: TraceOpts, order: Fn<
|
|
33
|
+
export declare const traceLines: (opts: TraceOpts, order: Fn<GridIterOpts2D, Iterable<[number, number]>>, border: Predicate<[number, number]>, tx: PointTransform2D, acc?: VecPair[]) => VecPair[];
|
|
34
34
|
/**
|
|
35
35
|
* Extracts single pixels and stores their coordinates in `acc`.
|
|
36
36
|
*
|
package/trace.js
CHANGED
|
@@ -69,10 +69,11 @@ export const traceBitmap = (opts) => {
|
|
|
69
69
|
* @param acc
|
|
70
70
|
*/
|
|
71
71
|
export const traceLines = (opts, order, border, tx, acc = []) => {
|
|
72
|
-
let { img, select, clear, last, min } = {
|
|
72
|
+
let { img, select, clear, last, min, max } = {
|
|
73
73
|
clear: 0,
|
|
74
74
|
last: true,
|
|
75
75
|
min: 2,
|
|
76
|
+
max: Infinity,
|
|
76
77
|
...opts,
|
|
77
78
|
};
|
|
78
79
|
min--;
|
|
@@ -84,11 +85,11 @@ export const traceLines = (opts, order, border, tx, acc = []) => {
|
|
|
84
85
|
img.setAtUnsafe(q[0], q[1], clear);
|
|
85
86
|
};
|
|
86
87
|
for (let p of order({ cols: img.width, rows: img.height, tx })) {
|
|
87
|
-
const c = select(img.getAtUnsafe(p[0], p[1]));
|
|
88
|
+
const c = select(img.getAtUnsafe(p[0], p[1]), p);
|
|
88
89
|
const isBorder = border(p);
|
|
89
90
|
const n = curr.length;
|
|
90
91
|
if (c) {
|
|
91
|
-
if (isBorder) {
|
|
92
|
+
if (isBorder || n >= max) {
|
|
92
93
|
if (n > 0) {
|
|
93
94
|
if (prevBorder) {
|
|
94
95
|
if (n > min)
|
|
@@ -133,7 +134,7 @@ export const tracePoints = ({ img, select, clear }, acc = []) => {
|
|
|
133
134
|
if (clear === undefined)
|
|
134
135
|
clear = 0;
|
|
135
136
|
for (let i = 0, n = img.data.length, w = img.width; i < n; i++) {
|
|
136
|
-
if (select(img.data[i])) {
|
|
137
|
+
if (select(img.data[i], [i % w, (i / w) | 0])) {
|
|
137
138
|
acc.push([i % w, (i / w) | 0]);
|
|
138
139
|
img.data[i] = clear;
|
|
139
140
|
}
|