@zappar/zappar-cv 0.4.0-beta.9 → 2.0.0-beta.0
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 -0
- package/README.md +2 -2
- package/lib/additional.d.ts +2 -1
- package/lib/additional.js +1 -2
- package/lib/camera-source-map.js +16 -24
- package/lib/camera-source.js +17 -21
- package/lib/cameramodel.js +18 -23
- package/lib/compatibility.js +1 -3
- package/lib/deserializer.js +1 -5
- package/lib/direct.js +12 -16
- package/lib/drawcamera.js +26 -31
- package/lib/drawface.js +5 -9
- package/lib/drawfaceproject.js +5 -9
- package/lib/drawplane.js +6 -11
- package/lib/event.js +5 -13
- package/lib/facelandmark.d.ts +1 -2
- package/lib/facelandmark.js +11 -18
- package/lib/facelandmarkdata.js +1 -4
- package/lib/facelandmarkinterface.js +1 -2
- package/lib/facemesh.js +10 -17
- package/lib/gen/zappar-client.js +5 -24
- package/lib/gen/zappar-cwrap.js +1 -12
- package/lib/gen/zappar-native.d.ts +0 -1
- package/lib/gen/zappar-native.js +10 -13
- package/lib/gen/zappar-server.js +5 -13
- package/lib/gen/zappar.d.ts +7 -0
- package/lib/gen/zappar.js +5 -13
- package/lib/gfx.js +1 -4
- package/lib/gl-state-manager.js +1 -5
- package/lib/html-element-source.js +23 -27
- package/lib/image-process-gl.js +29 -21
- package/lib/imagebitmap-camera-source.js +30 -34
- package/lib/imagetracker.d.ts +28 -0
- package/lib/imagetracker.js +115 -0
- package/lib/index-standalone.d.ts +3 -0
- package/lib/index-standalone.js +5 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +6 -27
- package/lib/landmarkdatagenerate.js +25 -30
- package/lib/loglevel.js +9 -16
- package/lib/messages.js +4 -8
- package/lib/mstp-camera-source.js +22 -26
- package/lib/native.d.ts +2 -1
- package/lib/native.js +194 -132
- package/lib/options.d.ts +3 -0
- package/lib/options.js +1 -0
- package/lib/permission.js +13 -27
- package/lib/pipeline.d.ts +1 -2
- package/lib/pipeline.js +34 -39
- package/lib/profile.js +40 -45
- package/lib/riff-reader.d.ts +18 -0
- package/lib/riff-reader.js +52 -0
- package/lib/sequencerecorder.js +7 -12
- package/lib/sequencesource.js +20 -24
- package/lib/serializer.js +1 -5
- package/lib/shader.js +2 -7
- package/lib/source.js +1 -5
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -4
- package/lib/worker-client.d.ts +1 -1
- package/lib/worker-client.js +9 -21
- package/lib/worker-imagebitmap.js +9 -13
- package/lib/worker-server.js +33 -37
- package/lib/worker.js +6 -10
- package/lib/workerinterface.js +1 -2
- package/lib/zcv.js +57 -57
- package/lib/zcv.wasm +0 -0
- package/package.json +14 -16
- package/umd/169.zappar-cv.js +1 -0
- package/umd/{482727c0e7dd40d73f5aae47f238ad61.zbin → 482727c0e7dd40d73f5a.zbin} +0 -0
- package/umd/{a78f5ad0a44def457ee50c8bcd5fd27c.wasm → 6a8309f88f836a752c68.wasm} +0 -0
- package/umd/752.zappar-cv.js +1 -0
- package/umd/{b4f46e148a3b3b5aef90717d8d60e3fc.zbin → b4f46e148a3b3b5aef90.zbin} +0 -0
- package/umd/{f7b62a3a53b5c9b3222ba8dc53cb8b11.zbin → f7b62a3a53b5c9b3222b.zbin} +0 -0
- package/umd/zappar-cv.js +1 -1
- package/umd/zappar-cv.worker.js +1 -1
package/lib/gl-state-manager.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GLStateManager = void 0;
|
|
4
1
|
const managers = new Map();
|
|
5
|
-
class GLStateManager {
|
|
2
|
+
export class GLStateManager {
|
|
6
3
|
constructor(_gl) {
|
|
7
4
|
this._gl = _gl;
|
|
8
5
|
this._viewports = [];
|
|
@@ -32,4 +29,3 @@ class GLStateManager {
|
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
}
|
|
35
|
-
exports.GLStateManager = GLStateManager;
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const gl_matrix_1 = require("gl-matrix");
|
|
8
|
-
const loglevel_1 = require("./loglevel");
|
|
9
|
-
const image_process_gl_1 = require("./image-process-gl");
|
|
1
|
+
import { Pipeline } from "./pipeline";
|
|
2
|
+
import { Source } from "./source";
|
|
3
|
+
import { profile } from "./profile";
|
|
4
|
+
import { mat4 } from "gl-matrix";
|
|
5
|
+
import { zcout } from "./loglevel";
|
|
6
|
+
import { ImageProcessGL } from "./image-process-gl";
|
|
10
7
|
let latest = 1;
|
|
11
8
|
let byId = new Map();
|
|
12
|
-
class HTMLElementSource extends
|
|
9
|
+
export class HTMLElementSource extends Source {
|
|
13
10
|
constructor(_video, _pipeline) {
|
|
14
11
|
super();
|
|
15
12
|
this._video = _video;
|
|
@@ -19,10 +16,10 @@ class HTMLElementSource extends source_1.Source {
|
|
|
19
16
|
this._isUserFacing = false;
|
|
20
17
|
this._cameraToScreenRotation = 0;
|
|
21
18
|
this._isUploadFrame = true;
|
|
22
|
-
this._cameraToDeviceTransform =
|
|
23
|
-
this._cameraToDeviceTransformUserFacing =
|
|
19
|
+
this._cameraToDeviceTransform = mat4.create();
|
|
20
|
+
this._cameraToDeviceTransformUserFacing = mat4.create();
|
|
24
21
|
this._cameraModel = new Float32Array([300, 300, 160, 120, 0, 0]);
|
|
25
|
-
|
|
22
|
+
mat4.fromScaling(this._cameraToDeviceTransformUserFacing, [-1, 1, -1]);
|
|
26
23
|
let video = this._video;
|
|
27
24
|
if (this._video instanceof HTMLVideoElement) {
|
|
28
25
|
video.addEventListener("loadedmetadata", () => { this._hadFrames = true; });
|
|
@@ -31,14 +28,14 @@ class HTMLElementSource extends source_1.Source {
|
|
|
31
28
|
this._hadFrames = true;
|
|
32
29
|
}
|
|
33
30
|
this._resetGLContext = this._resetGLContext.bind(this);
|
|
34
|
-
let p =
|
|
31
|
+
let p = Pipeline.get(this._pipeline);
|
|
35
32
|
if (p)
|
|
36
33
|
p.onGLContextReset.bind(this._resetGLContext);
|
|
37
34
|
}
|
|
38
35
|
static createVideoElementSource(p, element) {
|
|
39
36
|
let ret = (latest++);
|
|
40
37
|
byId.set(ret, new HTMLElementSource(element, p));
|
|
41
|
-
|
|
38
|
+
zcout("html_element_source_t initialized");
|
|
42
39
|
return ret;
|
|
43
40
|
}
|
|
44
41
|
static getVideoElementSource(m) {
|
|
@@ -50,7 +47,7 @@ class HTMLElementSource extends source_1.Source {
|
|
|
50
47
|
(_b = (_a = this._imageProcessor) === null || _a === void 0 ? void 0 : _a.resetGLContext) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
51
48
|
}
|
|
52
49
|
destroy() {
|
|
53
|
-
let p =
|
|
50
|
+
let p = Pipeline.get(this._pipeline);
|
|
54
51
|
if (p)
|
|
55
52
|
p.onGLContextReset.unbind(this._resetGLContext);
|
|
56
53
|
this.pause();
|
|
@@ -58,7 +55,7 @@ class HTMLElementSource extends source_1.Source {
|
|
|
58
55
|
}
|
|
59
56
|
pause() {
|
|
60
57
|
this._isPaused = true;
|
|
61
|
-
let p =
|
|
58
|
+
let p = Pipeline.get(this._pipeline);
|
|
62
59
|
if (p && p.currentCameraSource === this)
|
|
63
60
|
p.currentCameraSource = undefined;
|
|
64
61
|
}
|
|
@@ -70,14 +67,14 @@ class HTMLElementSource extends source_1.Source {
|
|
|
70
67
|
this._hadFrames = false;
|
|
71
68
|
}
|
|
72
69
|
this._isPaused = false;
|
|
73
|
-
let p =
|
|
70
|
+
let p = Pipeline.get(this._pipeline);
|
|
74
71
|
if (p && p.currentCameraSource !== this) {
|
|
75
72
|
(_a = p.currentCameraSource) === null || _a === void 0 ? void 0 : _a.pause();
|
|
76
73
|
p.currentCameraSource = this;
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
76
|
getFrame(currentlyProcessing) {
|
|
80
|
-
let pipeline =
|
|
77
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
81
78
|
if (!pipeline)
|
|
82
79
|
return;
|
|
83
80
|
let gl = pipeline.glContext;
|
|
@@ -100,11 +97,11 @@ class HTMLElementSource extends source_1.Source {
|
|
|
100
97
|
return;
|
|
101
98
|
}
|
|
102
99
|
_processFrame(gl, rotation, currentlyProcessing) {
|
|
103
|
-
let pipeline =
|
|
100
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
104
101
|
if (!pipeline)
|
|
105
102
|
return undefined;
|
|
106
103
|
if (!this._imageProcessor)
|
|
107
|
-
this._imageProcessor = new
|
|
104
|
+
this._imageProcessor = new ImageProcessGL(gl);
|
|
108
105
|
if (this._isUploadFrame) {
|
|
109
106
|
if (!this._currentVideoTexture) {
|
|
110
107
|
this._currentVideoTexture = pipeline.getVideoTexture();
|
|
@@ -118,7 +115,7 @@ class HTMLElementSource extends source_1.Source {
|
|
|
118
115
|
if (currentlyProcessing || !this._currentVideoTexture)
|
|
119
116
|
return undefined;
|
|
120
117
|
this._isUploadFrame = !this._isUploadFrame;
|
|
121
|
-
let greySize =
|
|
118
|
+
let greySize = profile.dataWidth * profile.dataHeight;
|
|
122
119
|
let pixels = pipeline.cameraPixelArrays.pop();
|
|
123
120
|
while (pixels) {
|
|
124
121
|
if (pixels.byteLength === greySize)
|
|
@@ -130,15 +127,14 @@ class HTMLElementSource extends source_1.Source {
|
|
|
130
127
|
}
|
|
131
128
|
let tex = this._currentVideoTexture;
|
|
132
129
|
this._currentVideoTexture = undefined;
|
|
133
|
-
let focalLength = 300.0 *
|
|
130
|
+
let focalLength = 300.0 * profile.dataWidth / 320.0;
|
|
134
131
|
this._cameraModel[0] = focalLength;
|
|
135
132
|
this._cameraModel[1] = focalLength;
|
|
136
|
-
this._cameraModel[2] =
|
|
137
|
-
this._cameraModel[3] =
|
|
138
|
-
return Object.assign(Object.assign({}, this._imageProcessor.readFrame(tex, pixels)), { cameraModel: this._cameraModel, cameraSource: this, cameraToDevice: this._isUserFacing ? this._cameraToDeviceTransformUserFacing : this._cameraToDeviceTransform });
|
|
133
|
+
this._cameraModel[2] = profile.dataWidth * 0.5;
|
|
134
|
+
this._cameraModel[3] = profile.dataHeight * 0.5;
|
|
135
|
+
return Object.assign(Object.assign({}, this._imageProcessor.readFrame(tex, pixels)), { cameraModel: this._cameraModel, cameraSource: this, cameraToDevice: (this._isUserFacing ? this._cameraToDeviceTransformUserFacing : this._cameraToDeviceTransform) });
|
|
139
136
|
}
|
|
140
137
|
uploadGL() {
|
|
141
138
|
// No-op as already uploaded
|
|
142
139
|
}
|
|
143
140
|
}
|
|
144
|
-
exports.HTMLElementSource = HTMLElementSource;
|
package/lib/image-process-gl.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const profile_1 = require("./profile");
|
|
7
|
-
const shader_1 = require("./shader");
|
|
8
|
-
class ImageProcessGL {
|
|
1
|
+
import { mat4 } from "gl-matrix";
|
|
2
|
+
import { GLStateManager } from "./gl-state-manager";
|
|
3
|
+
import { profile } from "./profile";
|
|
4
|
+
import { compileShader, linkProgram } from "./shader";
|
|
5
|
+
export class ImageProcessGL {
|
|
9
6
|
constructor(_gl) {
|
|
10
7
|
this._gl = _gl;
|
|
11
8
|
this._isPaused = true;
|
|
@@ -15,7 +12,7 @@ class ImageProcessGL {
|
|
|
15
12
|
this._isUploadFrame = true;
|
|
16
13
|
this._computedTransformRotation = -1;
|
|
17
14
|
this._computedFrontCameraRotation = false;
|
|
18
|
-
this._cameraUvTransform =
|
|
15
|
+
this._cameraUvTransform = mat4.create();
|
|
19
16
|
this._framebufferWidth = 0;
|
|
20
17
|
this._framebufferHeight = 0;
|
|
21
18
|
this._framebufferId = null;
|
|
@@ -33,7 +30,7 @@ class ImageProcessGL {
|
|
|
33
30
|
}
|
|
34
31
|
uploadFrame(texture, img, rotation, fc) {
|
|
35
32
|
let gl = this._gl;
|
|
36
|
-
const glStateManager =
|
|
33
|
+
const glStateManager = GLStateManager.get(gl);
|
|
37
34
|
glStateManager.push();
|
|
38
35
|
const reenableScissorTest = gl.isEnabled(gl.SCISSOR_TEST);
|
|
39
36
|
const reenableDepthTest = gl.isEnabled(gl.DEPTH_TEST);
|
|
@@ -71,7 +68,7 @@ class ImageProcessGL {
|
|
|
71
68
|
if (videoHeight > videoWidth)
|
|
72
69
|
videoHeight = [videoWidth, videoWidth = videoHeight][0];
|
|
73
70
|
this._updateTransforms(rotation, fc);
|
|
74
|
-
let framebuffer = this._getFramebuffer(gl,
|
|
71
|
+
let framebuffer = this._getFramebuffer(gl, profile.dataWidth / 4, profile.dataHeight);
|
|
75
72
|
let vbo = this._getVertexBuffer(gl);
|
|
76
73
|
let ibo = this._getIndexBuffer(gl);
|
|
77
74
|
let shader = this._getGreyscaleShader(gl);
|
|
@@ -80,11 +77,15 @@ class ImageProcessGL {
|
|
|
80
77
|
const previousVertexAttribNormalized = gl.getVertexAttrib(shader.aVertexPositionLoc, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED);
|
|
81
78
|
const previousVertexAttribStride = gl.getVertexAttrib(shader.aVertexPositionLoc, gl.VERTEX_ATTRIB_ARRAY_STRIDE);
|
|
82
79
|
const previousVertexAttribOffset = gl.getVertexAttribOffset(shader.aVertexPositionLoc, gl.VERTEX_ATTRIB_ARRAY_POINTER);
|
|
80
|
+
const previousVertexAttribEnabled = gl.getVertexAttrib(shader.aVertexPositionLoc, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
|
|
81
|
+
const previousVertexAttribBufferBinding = gl.getVertexAttrib(shader.aVertexPositionLoc, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
|
|
83
82
|
const previousTextureAttribSize = gl.getVertexAttrib(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_SIZE);
|
|
84
83
|
const previousTextureAttribType = gl.getVertexAttrib(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_TYPE);
|
|
85
84
|
const previousTextureAttribNormalized = gl.getVertexAttrib(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED);
|
|
86
85
|
const previousTextureAttribStride = gl.getVertexAttrib(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_STRIDE);
|
|
87
86
|
const previousTextureAttribOffset = gl.getVertexAttribOffset(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_POINTER);
|
|
87
|
+
const previousTextureAttribEnabled = gl.getVertexAttrib(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
|
|
88
|
+
const previousTextureAttribBufferBinding = gl.getVertexAttrib(shader.aTextureCoordLoc, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
|
|
88
89
|
// Rendering to the greyscale conversion buffer - bind the framebuffer
|
|
89
90
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
90
91
|
gl.viewport(0, 0, this._framebufferWidth, this._framebufferHeight);
|
|
@@ -101,7 +102,7 @@ class ImageProcessGL {
|
|
|
101
102
|
// Tell WebGL to use our program when drawing
|
|
102
103
|
gl.useProgram(shader.program);
|
|
103
104
|
// Specify greyscale width for the correct offsets, and the uv transform
|
|
104
|
-
gl.uniform1f(shader.uTexWidthLoc,
|
|
105
|
+
gl.uniform1f(shader.uTexWidthLoc, profile.dataWidth);
|
|
105
106
|
gl.uniformMatrix4fv(shader.uUvTransformLoc, false, this._cameraUvTransform);
|
|
106
107
|
gl.activeTexture(gl.TEXTURE0);
|
|
107
108
|
// Bind the texture to texture unit 0
|
|
@@ -110,15 +111,22 @@ class ImageProcessGL {
|
|
|
110
111
|
gl.uniform1i(shader.uSamplerLoc, 0);
|
|
111
112
|
// Do the drawing...
|
|
112
113
|
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
|
114
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, previousVertexAttribBufferBinding);
|
|
113
115
|
gl.vertexAttribPointer(shader.aVertexPositionLoc, previousVertexAttribSize, previousVertexAttribType, previousVertexAttribNormalized, previousVertexAttribStride, previousVertexAttribOffset);
|
|
116
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, previousTextureAttribBufferBinding);
|
|
114
117
|
gl.vertexAttribPointer(shader.aTextureCoordLoc, previousTextureAttribSize, previousTextureAttribType, previousTextureAttribNormalized, previousTextureAttribStride, previousTextureAttribOffset);
|
|
115
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, previousBoundFramebuffer);
|
|
116
118
|
gl.bindBuffer(gl.ARRAY_BUFFER, previousBoundArrayBuffer);
|
|
117
119
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, previousBoundElementArrayBuffer);
|
|
120
|
+
if (!previousVertexAttribEnabled)
|
|
121
|
+
gl.disableVertexAttribArray(shader.aVertexPositionLoc);
|
|
122
|
+
if (!previousTextureAttribEnabled)
|
|
123
|
+
gl.disableVertexAttribArray(shader.aTextureCoordLoc);
|
|
124
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, previousBoundFramebuffer);
|
|
118
125
|
gl.useProgram(previousProgram);
|
|
119
126
|
gl.bindTexture(gl.TEXTURE_2D, previousBoundTexture);
|
|
120
127
|
gl.activeTexture(previousActiveTexture);
|
|
121
128
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, previousUnpackFlip);
|
|
129
|
+
glStateManager.pop();
|
|
122
130
|
if (reenableBlend)
|
|
123
131
|
gl.enable(gl.BLEND);
|
|
124
132
|
if (reenableCullFace)
|
|
@@ -131,8 +139,8 @@ class ImageProcessGL {
|
|
|
131
139
|
readFrame(texture, pixels) {
|
|
132
140
|
let gl = this._gl;
|
|
133
141
|
let pixelsView = new Uint8Array(pixels);
|
|
134
|
-
let framebuffer = this._getFramebuffer(gl, profile_1.profile.dataWidth / 4, profile_1.profile.dataHeight);
|
|
135
142
|
const previousBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
|
|
143
|
+
let framebuffer = this._getFramebuffer(gl, profile.dataWidth / 4, profile.dataHeight);
|
|
136
144
|
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
137
145
|
gl.readPixels(0, 0, this._framebufferWidth, this._framebufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixelsView);
|
|
138
146
|
gl.bindFramebuffer(gl.FRAMEBUFFER, previousBoundFramebuffer);
|
|
@@ -140,8 +148,8 @@ class ImageProcessGL {
|
|
|
140
148
|
uvTransform: this._cameraUvTransform,
|
|
141
149
|
data: pixels,
|
|
142
150
|
texture,
|
|
143
|
-
dataWidth:
|
|
144
|
-
dataHeight:
|
|
151
|
+
dataWidth: profile.dataWidth,
|
|
152
|
+
dataHeight: profile.dataHeight,
|
|
145
153
|
userFacing: this._computedFrontCameraRotation
|
|
146
154
|
};
|
|
147
155
|
}
|
|
@@ -179,6 +187,7 @@ class ImageProcessGL {
|
|
|
179
187
|
if (!this._renderTexture)
|
|
180
188
|
throw new Error("Unable to create render texture");
|
|
181
189
|
gl.activeTexture(gl.TEXTURE0);
|
|
190
|
+
const previousBoundTexture = gl.getParameter(gl.TEXTURE_BINDING_2D);
|
|
182
191
|
gl.bindTexture(gl.TEXTURE_2D, this._renderTexture);
|
|
183
192
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fbWidth, fbHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
184
193
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
@@ -190,7 +199,7 @@ class ImageProcessGL {
|
|
|
190
199
|
throw new Error("Framebuffer not complete: " + fbStatus.toString());
|
|
191
200
|
this._framebufferWidth = fbWidth;
|
|
192
201
|
this._framebufferHeight = fbHeight;
|
|
193
|
-
gl.bindTexture(gl.TEXTURE_2D,
|
|
202
|
+
gl.bindTexture(gl.TEXTURE_2D, previousBoundTexture);
|
|
194
203
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
195
204
|
return this._framebufferId;
|
|
196
205
|
}
|
|
@@ -225,11 +234,11 @@ class ImageProcessGL {
|
|
|
225
234
|
let prog = gl.createProgram();
|
|
226
235
|
if (!prog)
|
|
227
236
|
throw new Error("Unable to create program");
|
|
228
|
-
let vertexShader =
|
|
229
|
-
let fragmentShader =
|
|
237
|
+
let vertexShader = compileShader(gl, gl.VERTEX_SHADER, greyscaleVsSource);
|
|
238
|
+
let fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, greyscaleFsSource);
|
|
230
239
|
gl.attachShader(prog, vertexShader);
|
|
231
240
|
gl.attachShader(prog, fragmentShader);
|
|
232
|
-
|
|
241
|
+
linkProgram(gl, prog);
|
|
233
242
|
let uTexWidthLoc = gl.getUniformLocation(prog, "uTexWidth");
|
|
234
243
|
if (!uTexWidthLoc)
|
|
235
244
|
throw new Error("Unable to get uniform location uTexWidth");
|
|
@@ -250,7 +259,6 @@ class ImageProcessGL {
|
|
|
250
259
|
return this._greyscaleShader;
|
|
251
260
|
}
|
|
252
261
|
}
|
|
253
|
-
exports.ImageProcessGL = ImageProcessGL;
|
|
254
262
|
let greyscaleVsSource = `
|
|
255
263
|
attribute vec4 aVertexPosition;
|
|
256
264
|
attribute vec2 aTextureCoord;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,16 +7,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
8
|
});
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const gl_matrix_1 = require("gl-matrix");
|
|
20
|
-
class ImageBitmapCameraSource extends source_1.Source {
|
|
10
|
+
import { profile } from "./profile";
|
|
11
|
+
import { Pipeline } from "./pipeline";
|
|
12
|
+
import { Source } from "./source";
|
|
13
|
+
import { cameraRotationForScreenOrientation } from "./cameramodel";
|
|
14
|
+
import { zcout } from "./loglevel";
|
|
15
|
+
import { deleteCameraSource } from "./camera-source-map";
|
|
16
|
+
import { mat4 } from "gl-matrix";
|
|
17
|
+
export class ImageBitmapCameraSource extends Source {
|
|
21
18
|
constructor(_impl, _pipeline, _deviceId) {
|
|
22
19
|
super();
|
|
23
20
|
this._impl = _impl;
|
|
@@ -32,12 +29,12 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
32
29
|
this._context = this._canvas.getContext("2d");
|
|
33
30
|
this._lastFrameTime = -1;
|
|
34
31
|
this._video = document.createElement("video");
|
|
35
|
-
this._cameraToDeviceTransform =
|
|
36
|
-
this._cameraToDeviceTransformUserFacing =
|
|
32
|
+
this._cameraToDeviceTransform = mat4.create();
|
|
33
|
+
this._cameraToDeviceTransformUserFacing = mat4.create();
|
|
37
34
|
this._cameraModel = new Float32Array([300, 300, 160, 120, 0, 0]);
|
|
38
35
|
this._hasStartedOrientation = false;
|
|
39
36
|
this._deviceMotionListener = (ev) => {
|
|
40
|
-
let pipeline =
|
|
37
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
41
38
|
if (!pipeline)
|
|
42
39
|
return;
|
|
43
40
|
let timeStamp = (ev.timeStamp !== undefined && ev.timeStamp !== null) ? ev.timeStamp : performance.now();
|
|
@@ -45,7 +42,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
45
42
|
ev.accelerationIncludingGravity.x !== null &&
|
|
46
43
|
ev.accelerationIncludingGravity.y !== null &&
|
|
47
44
|
ev.accelerationIncludingGravity.z !== null) {
|
|
48
|
-
pipeline.motionAccelerometerSubmit(timeStamp, ev.accelerationIncludingGravity.x *
|
|
45
|
+
pipeline.motionAccelerometerSubmit(timeStamp, ev.accelerationIncludingGravity.x * profile.deviceMotionMutliplier, ev.accelerationIncludingGravity.y * profile.deviceMotionMutliplier, ev.accelerationIncludingGravity.z * profile.deviceMotionMutliplier);
|
|
49
46
|
}
|
|
50
47
|
if (ev.rotationRate !== null &&
|
|
51
48
|
ev.rotationRate.alpha !== null &&
|
|
@@ -58,12 +55,12 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
58
55
|
this._startDeviceOrientation();
|
|
59
56
|
}
|
|
60
57
|
};
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
zcout("Using ImageBitmap camera source");
|
|
59
|
+
mat4.fromScaling(this._cameraToDeviceTransformUserFacing, [-1, 1, -1]);
|
|
63
60
|
this._video.muted = true;
|
|
64
61
|
this._video.setAttribute('playsinline', '');
|
|
65
62
|
this._video.setAttribute('webkit-playsinline', '');
|
|
66
|
-
if (
|
|
63
|
+
if (profile.videoElementInDOM) {
|
|
67
64
|
this._video.style.width = "0px";
|
|
68
65
|
this._video.style.height = "0px";
|
|
69
66
|
document.body.appendChild(this._video);
|
|
@@ -72,7 +69,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
72
69
|
}
|
|
73
70
|
destroy() {
|
|
74
71
|
this.pause();
|
|
75
|
-
|
|
72
|
+
deleteCameraSource(this._impl);
|
|
76
73
|
}
|
|
77
74
|
_stop() {
|
|
78
75
|
if (!this._currentStream)
|
|
@@ -83,7 +80,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
83
80
|
}
|
|
84
81
|
pause() {
|
|
85
82
|
this._isPaused = true;
|
|
86
|
-
let p =
|
|
83
|
+
let p = Pipeline.get(this._pipeline);
|
|
87
84
|
if (p && p.currentCameraSource === this)
|
|
88
85
|
p.currentCameraSource = undefined;
|
|
89
86
|
this._stopDeviceMotion();
|
|
@@ -91,7 +88,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
91
88
|
}
|
|
92
89
|
start() {
|
|
93
90
|
var _a;
|
|
94
|
-
let p =
|
|
91
|
+
let p = Pipeline.get(this._pipeline);
|
|
95
92
|
if (p && p.currentCameraSource !== this) {
|
|
96
93
|
(_a = p.currentCameraSource) === null || _a === void 0 ? void 0 : _a.pause();
|
|
97
94
|
p.currentCameraSource = this;
|
|
@@ -116,9 +113,9 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
116
113
|
audio: false,
|
|
117
114
|
video: {
|
|
118
115
|
facingMode: facingMode,
|
|
119
|
-
width:
|
|
120
|
-
height:
|
|
121
|
-
frameRate:
|
|
116
|
+
width: profile.videoWidth,
|
|
117
|
+
height: profile.videoHeight,
|
|
118
|
+
frameRate: profile.requestHighFrameRate ? 60 : undefined,
|
|
122
119
|
deviceId: deviceId
|
|
123
120
|
}
|
|
124
121
|
};
|
|
@@ -146,7 +143,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
146
143
|
return constraints;
|
|
147
144
|
}
|
|
148
145
|
if (typeof constraints.video === "object") {
|
|
149
|
-
|
|
146
|
+
zcout("choosing device ID", devices[devices.length - 1].deviceId);
|
|
150
147
|
constraints.video.deviceId = devices[devices.length - 1].deviceId;
|
|
151
148
|
}
|
|
152
149
|
return constraints;
|
|
@@ -170,15 +167,15 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
170
167
|
this._canvas.height = this._video.videoHeight;
|
|
171
168
|
this._context.drawImage(this._video, 0, 0);
|
|
172
169
|
const imageBitmap = this._canvas.transferToImageBitmap();
|
|
173
|
-
let rotation =
|
|
174
|
-
let pipeline =
|
|
170
|
+
let rotation = cameraRotationForScreenOrientation(false);
|
|
171
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
175
172
|
if (!pipeline)
|
|
176
173
|
return;
|
|
177
|
-
let focalLength = 300.0 *
|
|
174
|
+
let focalLength = 300.0 * profile.dataWidth / 320.0;
|
|
178
175
|
this._cameraModel[0] = focalLength;
|
|
179
176
|
this._cameraModel[1] = focalLength;
|
|
180
|
-
this._cameraModel[2] =
|
|
181
|
-
this._cameraModel[3] =
|
|
177
|
+
this._cameraModel[2] = profile.dataWidth * 0.5;
|
|
178
|
+
this._cameraModel[3] = profile.dataHeight * 0.5;
|
|
182
179
|
let token = pipeline.registerToken({
|
|
183
180
|
dataWidth: this._canvas.width,
|
|
184
181
|
dataHeight: this._canvas.height,
|
|
@@ -188,7 +185,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
188
185
|
cameraModel: this._cameraModel.slice(),
|
|
189
186
|
cameraToDevice: this._isUserFacing ? this._cameraToDeviceTransformUserFacing : this._cameraToDeviceTransform
|
|
190
187
|
});
|
|
191
|
-
(_b = (_a =
|
|
188
|
+
(_b = (_a = Pipeline.get(this._pipeline)) === null || _a === void 0 ? void 0 : _a.sendImageBitmapToWorker) === null || _b === void 0 ? void 0 : _b.call(_a, imageBitmap, rotation, this._isUserFacing, token, this._cameraModel, this._isUserFacing ? this._cameraToDeviceTransformUserFacing : this._cameraToDeviceTransform);
|
|
192
189
|
return;
|
|
193
190
|
}
|
|
194
191
|
_getUserMedia() {
|
|
@@ -236,7 +233,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
236
233
|
return;
|
|
237
234
|
this._hasStartedOrientation = true;
|
|
238
235
|
window.addEventListener("deviceorientation", (ev) => {
|
|
239
|
-
let pipeline =
|
|
236
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
240
237
|
if (!pipeline)
|
|
241
238
|
return;
|
|
242
239
|
let timeStamp = (ev.timeStamp !== undefined && ev.timeStamp !== null) ? ev.timeStamp : performance.now();
|
|
@@ -252,7 +249,7 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
252
249
|
window.removeEventListener("devicemotion", this._deviceMotionListener);
|
|
253
250
|
}
|
|
254
251
|
uploadGL(info) {
|
|
255
|
-
const pipeline =
|
|
252
|
+
const pipeline = Pipeline.get(this._pipeline);
|
|
256
253
|
const gl = pipeline === null || pipeline === void 0 ? void 0 : pipeline.glContext;
|
|
257
254
|
if (!info ||
|
|
258
255
|
info.texture ||
|
|
@@ -272,6 +269,5 @@ class ImageBitmapCameraSource extends source_1.Source {
|
|
|
272
269
|
delete info.frame;
|
|
273
270
|
}
|
|
274
271
|
}
|
|
275
|
-
exports.ImageBitmapCameraSource = ImageBitmapCameraSource;
|
|
276
272
|
ImageBitmapCameraSource.USER_DEFAULT_DEVICE_ID = "Simulated User Default Device ID: a908df7f-5661-4d20-b227-a1c15d2fdb4b";
|
|
277
273
|
ImageBitmapCameraSource.DEFAULT_DEVICE_ID = "Simulated Default Device ID: a908df7f-5661-4d20-b227-a1c15d2fdb4b";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { zappar_image_tracker_t, zappar_pipeline_t } from "./gen/zappar";
|
|
2
|
+
import { zappar_cwrap } from "./gen/zappar-native";
|
|
3
|
+
interface PreviewInfo {
|
|
4
|
+
compressed: Uint8Array;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
}
|
|
7
|
+
interface ParsedTargetInfo {
|
|
8
|
+
preview?: PreviewInfo;
|
|
9
|
+
physicalScaleFactor: number;
|
|
10
|
+
topRadius: number;
|
|
11
|
+
bottomRadius: number;
|
|
12
|
+
sideLength: number;
|
|
13
|
+
}
|
|
14
|
+
export declare class ImageTracker {
|
|
15
|
+
private _client;
|
|
16
|
+
private _impl;
|
|
17
|
+
private _targets;
|
|
18
|
+
static create(pipeline: zappar_pipeline_t, client: zappar_cwrap): zappar_image_tracker_t;
|
|
19
|
+
static get(p: zappar_image_tracker_t): ImageTracker | undefined;
|
|
20
|
+
private constructor();
|
|
21
|
+
destroy(): void;
|
|
22
|
+
loadFromMemory(data: ArrayBuffer): void;
|
|
23
|
+
targetCount(): number;
|
|
24
|
+
getTargetInfo(i: number): ParsedTargetInfo;
|
|
25
|
+
private _parseOdle;
|
|
26
|
+
getDecodedPreview(i: number): HTMLImageElement | undefined;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { RiffReader } from "./riff-reader";
|
|
2
|
+
let byId = new Map();
|
|
3
|
+
const decoder = new TextDecoder();
|
|
4
|
+
export class ImageTracker {
|
|
5
|
+
constructor(_client, _impl) {
|
|
6
|
+
this._client = _client;
|
|
7
|
+
this._impl = _impl;
|
|
8
|
+
this._targets = [];
|
|
9
|
+
}
|
|
10
|
+
static create(pipeline, client) {
|
|
11
|
+
let ret = client.image_tracker_create(pipeline);
|
|
12
|
+
byId.set(ret, new ImageTracker(client, ret));
|
|
13
|
+
return ret;
|
|
14
|
+
}
|
|
15
|
+
static get(p) {
|
|
16
|
+
return byId.get(p);
|
|
17
|
+
}
|
|
18
|
+
destroy() {
|
|
19
|
+
this._client.image_tracker_destroy(this._impl);
|
|
20
|
+
byId.delete(this._impl);
|
|
21
|
+
}
|
|
22
|
+
loadFromMemory(data) {
|
|
23
|
+
this._targets.push({ data });
|
|
24
|
+
this._client.image_tracker_target_load_from_memory(this._impl, data);
|
|
25
|
+
}
|
|
26
|
+
targetCount() {
|
|
27
|
+
return this._targets.length;
|
|
28
|
+
}
|
|
29
|
+
getTargetInfo(i) {
|
|
30
|
+
let current = this._targets[i];
|
|
31
|
+
if (current && current.info)
|
|
32
|
+
return current.info;
|
|
33
|
+
current.info = {
|
|
34
|
+
topRadius: -1,
|
|
35
|
+
bottomRadius: -1,
|
|
36
|
+
sideLength: -1,
|
|
37
|
+
physicalScaleFactor: -1
|
|
38
|
+
};
|
|
39
|
+
try {
|
|
40
|
+
const reader = new RiffReader(current.data, false);
|
|
41
|
+
const imgChunk = reader.find("IMG ");
|
|
42
|
+
if (imgChunk) {
|
|
43
|
+
let mimeType = "image/png";
|
|
44
|
+
const mimeTypeChunk = reader.find("IMGM");
|
|
45
|
+
if (mimeTypeChunk)
|
|
46
|
+
mimeType = decoder.decode(mimeTypeChunk.data);
|
|
47
|
+
current.info.preview = { mimeType, compressed: imgChunk.data };
|
|
48
|
+
}
|
|
49
|
+
const odleChunk = reader.find("ODLE");
|
|
50
|
+
if (odleChunk) {
|
|
51
|
+
const odle = decoder.decode(odleChunk.data);
|
|
52
|
+
this._parseOdle(odle, current.info);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) { }
|
|
56
|
+
return current.info;
|
|
57
|
+
}
|
|
58
|
+
_parseOdle(data, info) {
|
|
59
|
+
let currentOffset = 0;
|
|
60
|
+
let version = "0";
|
|
61
|
+
[version, currentOffset] = readLine(currentOffset, data);
|
|
62
|
+
if (version === "3") {
|
|
63
|
+
let treeOrFlat = "0";
|
|
64
|
+
[treeOrFlat, currentOffset] = readLine(currentOffset, data);
|
|
65
|
+
if (treeOrFlat !== "0" && treeOrFlat !== "1")
|
|
66
|
+
return;
|
|
67
|
+
let numberTargets = "0";
|
|
68
|
+
[numberTargets, currentOffset] = readLine(currentOffset, data);
|
|
69
|
+
const parsedTargets = parseInt(numberTargets);
|
|
70
|
+
if (isNaN(parsedTargets) || parsedTargets < 1)
|
|
71
|
+
return;
|
|
72
|
+
let emptyLine = "";
|
|
73
|
+
[emptyLine, currentOffset] = readLine(currentOffset, data);
|
|
74
|
+
if (emptyLine.length !== 0)
|
|
75
|
+
return;
|
|
76
|
+
let infoLine = "";
|
|
77
|
+
[infoLine, currentOffset] = readLine(currentOffset, data);
|
|
78
|
+
const infoLineParts = infoLine.split(" ");
|
|
79
|
+
if (infoLineParts.length < 7)
|
|
80
|
+
return;
|
|
81
|
+
info.physicalScaleFactor = parseFloat(infoLineParts[6]);
|
|
82
|
+
if (isNaN(info.physicalScaleFactor))
|
|
83
|
+
info.physicalScaleFactor = -1;
|
|
84
|
+
if (infoLineParts.length >= 8) {
|
|
85
|
+
info.topRadius = parseFloat(infoLineParts[7]);
|
|
86
|
+
if (isNaN(info.topRadius))
|
|
87
|
+
info.topRadius = -1;
|
|
88
|
+
info.bottomRadius = info.topRadius;
|
|
89
|
+
}
|
|
90
|
+
if (infoLineParts.length >= 9) {
|
|
91
|
+
info.bottomRadius = parseFloat(infoLineParts[8]);
|
|
92
|
+
if (isNaN(info.bottomRadius))
|
|
93
|
+
info.bottomRadius = -1;
|
|
94
|
+
}
|
|
95
|
+
if (infoLineParts.length >= 10) {
|
|
96
|
+
info.sideLength = parseFloat(infoLineParts[9]);
|
|
97
|
+
if (isNaN(info.sideLength))
|
|
98
|
+
info.sideLength = -1;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
getDecodedPreview(i) {
|
|
103
|
+
const info = this.getTargetInfo(i);
|
|
104
|
+
if (!info.preview)
|
|
105
|
+
return undefined;
|
|
106
|
+
const blob = new Blob([info.preview.compressed], { type: info.preview.mimeType });
|
|
107
|
+
const image = new Image();
|
|
108
|
+
image.src = URL.createObjectURL(blob);
|
|
109
|
+
return image;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function readLine(offset, str) {
|
|
113
|
+
let indx = str.indexOf("\n", offset);
|
|
114
|
+
return [str.substring(offset, indx >= 0 ? indx : undefined).replace("\r", ""), indx + 1];
|
|
115
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { initialize as init } from "./index";
|
|
2
|
+
export * from "./index";
|
|
3
|
+
export function initialize(opts) {
|
|
4
|
+
return init(Object.assign(Object.assign({}, opts), { worker: (opts === null || opts === void 0 ? void 0 : opts.worker) || new (require("worker-loader?inline=fallback!./worker").default)() }));
|
|
5
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { zappar } from "./gen/zappar";
|
|
2
2
|
import { Additional } from "./additional";
|
|
3
|
+
import { Options } from "./options";
|
|
3
4
|
export declare type Zappar = zappar & Additional;
|
|
4
|
-
export declare function initialize(): Zappar;
|
|
5
|
+
export declare function initialize(opts?: Options): Zappar;
|
|
5
6
|
export { zappar_image_tracker_t, zappar_instant_world_tracker_t, zappar_barcode_finder_t, zappar_face_tracker_t, zappar_face_landmark_t, barcode_format_t, face_landmark_name_t, instant_world_tracker_transform_orientation_t, log_level_t, zappar_face_mesh_t, zappar_pipeline_t, zappar_camera_source_t, zappar_sequence_source_t } from "./gen/zappar";
|