@zappar/zappar-cv 0.4.0-beta.4 → 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 +91 -34
- package/README.md +2 -2
- package/lib/additional.d.ts +2 -1
- package/lib/additional.js +1 -2
- package/lib/camera-source-map.d.ts +10 -0
- package/lib/camera-source-map.js +32 -0
- package/lib/camera-source.d.ts +2 -5
- package/lib/camera-source.js +18 -32
- package/lib/cameramodel.js +18 -23
- package/lib/compatibility.js +2 -4
- package/lib/deserializer.js +1 -5
- package/lib/direct.js +12 -16
- package/lib/drawcamera.js +27 -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 +11 -25
- package/lib/gen/zappar-cwrap.js +38 -33
- package/lib/gen/zappar-native.d.ts +11 -1
- package/lib/gen/zappar-native.js +20 -11
- package/lib/gen/zappar-server.js +6 -14
- package/lib/gen/zappar.d.ts +12 -0
- package/lib/gen/zappar.js +5 -11
- package/lib/gfx.d.ts +1 -0
- package/lib/gfx.js +1 -0
- package/lib/gl-state-manager.d.ts +9 -0
- package/lib/gl-state-manager.js +31 -0
- package/lib/html-element-source.d.ts +3 -20
- package/lib/html-element-source.js +39 -287
- package/lib/image-process-gl.d.ts +37 -0
- package/lib/image-process-gl.js +306 -0
- package/lib/imagebitmap-camera-source.d.ts +36 -0
- package/lib/imagebitmap-camera-source.js +273 -0
- 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.d.ts +29 -0
- package/lib/mstp-camera-source.js +226 -0
- package/lib/native.d.ts +2 -1
- package/lib/native.js +229 -130
- package/lib/options.d.ts +3 -0
- package/lib/options.js +1 -0
- package/lib/permission.js +13 -27
- package/lib/pipeline.d.ts +14 -5
- package/lib/pipeline.js +125 -61
- package/lib/profile.d.ts +2 -0
- package/lib/profile.js +59 -53
- package/lib/riff-reader.d.ts +18 -0
- package/lib/riff-reader.js +52 -0
- package/lib/sequencerecorder.d.ts +1 -0
- package/lib/sequencerecorder.js +17 -11
- package/lib/sequencesource.d.ts +7 -1
- package/lib/sequencesource.js +102 -64
- package/lib/serializer.js +1 -5
- package/lib/shader.js +2 -7
- package/lib/source.d.ts +6 -4
- 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 -26
- package/lib/worker-imagebitmap.d.ts +5 -0
- package/lib/worker-imagebitmap.js +59 -0
- package/lib/worker-server.d.ts +0 -5
- package/lib/worker-server.js +133 -41
- package/lib/worker.js +6 -10
- package/lib/workerinterface.d.ts +47 -1
- package/lib/workerinterface.js +1 -2
- package/lib/zcv.js +117 -135
- package/lib/zcv.wasm +0 -0
- package/package.json +33 -32
- package/umd/169.zappar-cv.js +1 -0
- package/umd/{482727c0e7dd40d73f5aae47f238ad61.zbin → 482727c0e7dd40d73f5a.zbin} +0 -0
- package/umd/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 -9
- package/umd/zappar-cv.worker.js +1 -1
- package/lib/bundleworker-mainthread.d.ts +0 -2
- package/lib/bundleworker-mainthread.js +0 -36
- package/lib/bundleworker-worker.d.ts +0 -6
- package/lib/bundleworker-worker.js +0 -34
- package/lib/zcv-slam.js +0 -16
- package/lib/zcv-slam.wasm +0 -0
- package/umd/1ec038c18c27f4adf35917a8175401f0.wasm +0 -0
- package/umd/9c0b0dcf514b48c05541.bundleworker.js +0 -1
- package/umd/d115e485cffe500afc4f7c1272ea8f62.wasm +0 -0
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const shader_1 = require("./shader");
|
|
8
|
-
const gl_matrix_1 = require("gl-matrix");
|
|
9
|
-
const loglevel_1 = require("./loglevel");
|
|
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,17 +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.
|
|
23
|
-
this.
|
|
24
|
-
this._cameraUvTransform = gl_matrix_1.mat4.create();
|
|
25
|
-
this._cameraToDeviceTransform = gl_matrix_1.mat4.create();
|
|
26
|
-
this._cameraToDeviceTransformUserFacing = gl_matrix_1.mat4.create();
|
|
19
|
+
this._cameraToDeviceTransform = mat4.create();
|
|
20
|
+
this._cameraToDeviceTransformUserFacing = mat4.create();
|
|
27
21
|
this._cameraModel = new Float32Array([300, 300, 160, 120, 0, 0]);
|
|
28
|
-
this.
|
|
29
|
-
this._framebufferHeight = 0;
|
|
30
|
-
this._framebufferId = null;
|
|
31
|
-
this._renderTexture = null;
|
|
32
|
-
gl_matrix_1.mat4.fromScaling(this._cameraToDeviceTransformUserFacing, [-1, 1, -1]);
|
|
22
|
+
mat4.fromScaling(this._cameraToDeviceTransformUserFacing, [-1, 1, -1]);
|
|
33
23
|
let video = this._video;
|
|
34
24
|
if (this._video instanceof HTMLVideoElement) {
|
|
35
25
|
video.addEventListener("loadedmetadata", () => { this._hadFrames = true; });
|
|
@@ -38,29 +28,26 @@ class HTMLElementSource extends source_1.Source {
|
|
|
38
28
|
this._hadFrames = true;
|
|
39
29
|
}
|
|
40
30
|
this._resetGLContext = this._resetGLContext.bind(this);
|
|
41
|
-
let p =
|
|
31
|
+
let p = Pipeline.get(this._pipeline);
|
|
42
32
|
if (p)
|
|
43
33
|
p.onGLContextReset.bind(this._resetGLContext);
|
|
44
34
|
}
|
|
45
35
|
static createVideoElementSource(p, element) {
|
|
46
36
|
let ret = (latest++);
|
|
47
37
|
byId.set(ret, new HTMLElementSource(element, p));
|
|
48
|
-
|
|
38
|
+
zcout("html_element_source_t initialized");
|
|
49
39
|
return ret;
|
|
50
40
|
}
|
|
51
41
|
static getVideoElementSource(m) {
|
|
52
42
|
return byId.get(m);
|
|
53
43
|
}
|
|
54
44
|
_resetGLContext() {
|
|
45
|
+
var _a, _b;
|
|
55
46
|
this._currentVideoTexture = undefined;
|
|
56
|
-
this.
|
|
57
|
-
this._renderTexture = null;
|
|
58
|
-
this._vertexBuffer = undefined;
|
|
59
|
-
this._indexBuffer = undefined;
|
|
60
|
-
this._greyscaleShader = undefined;
|
|
47
|
+
(_b = (_a = this._imageProcessor) === null || _a === void 0 ? void 0 : _a.resetGLContext) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
61
48
|
}
|
|
62
49
|
destroy() {
|
|
63
|
-
let p =
|
|
50
|
+
let p = Pipeline.get(this._pipeline);
|
|
64
51
|
if (p)
|
|
65
52
|
p.onGLContextReset.unbind(this._resetGLContext);
|
|
66
53
|
this.pause();
|
|
@@ -68,7 +55,7 @@ class HTMLElementSource extends source_1.Source {
|
|
|
68
55
|
}
|
|
69
56
|
pause() {
|
|
70
57
|
this._isPaused = true;
|
|
71
|
-
let p =
|
|
58
|
+
let p = Pipeline.get(this._pipeline);
|
|
72
59
|
if (p && p.currentCameraSource === this)
|
|
73
60
|
p.currentCameraSource = undefined;
|
|
74
61
|
}
|
|
@@ -80,14 +67,14 @@ class HTMLElementSource extends source_1.Source {
|
|
|
80
67
|
this._hadFrames = false;
|
|
81
68
|
}
|
|
82
69
|
this._isPaused = false;
|
|
83
|
-
let p =
|
|
70
|
+
let p = Pipeline.get(this._pipeline);
|
|
84
71
|
if (p && p.currentCameraSource !== this) {
|
|
85
72
|
(_a = p.currentCameraSource) === null || _a === void 0 ? void 0 : _a.pause();
|
|
86
73
|
p.currentCameraSource = this;
|
|
87
74
|
}
|
|
88
75
|
}
|
|
89
76
|
getFrame(currentlyProcessing) {
|
|
90
|
-
let pipeline =
|
|
77
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
91
78
|
if (!pipeline)
|
|
92
79
|
return;
|
|
93
80
|
let gl = pipeline.glContext;
|
|
@@ -98,7 +85,11 @@ class HTMLElementSource extends source_1.Source {
|
|
|
98
85
|
if (!this._hadFrames)
|
|
99
86
|
return;
|
|
100
87
|
try {
|
|
101
|
-
|
|
88
|
+
let info = this._processFrame(gl, this._cameraToScreenRotation, currentlyProcessing);
|
|
89
|
+
if (info) {
|
|
90
|
+
let token = pipeline.registerToken(info);
|
|
91
|
+
pipeline.sendDataToWorker(info.data || new ArrayBuffer(0), token, info.dataWidth, info.dataHeight, info.userFacing, info.cameraToDevice, info.cameraModel);
|
|
92
|
+
}
|
|
102
93
|
}
|
|
103
94
|
catch (ex) {
|
|
104
95
|
console.log("Unable to process frame");
|
|
@@ -106,283 +97,44 @@ class HTMLElementSource extends source_1.Source {
|
|
|
106
97
|
return;
|
|
107
98
|
}
|
|
108
99
|
_processFrame(gl, rotation, currentlyProcessing) {
|
|
109
|
-
let pipeline =
|
|
100
|
+
let pipeline = Pipeline.get(this._pipeline);
|
|
110
101
|
if (!pipeline)
|
|
111
102
|
return undefined;
|
|
103
|
+
if (!this._imageProcessor)
|
|
104
|
+
this._imageProcessor = new ImageProcessGL(gl);
|
|
112
105
|
if (this._isUploadFrame) {
|
|
113
106
|
if (!this._currentVideoTexture) {
|
|
114
107
|
this._currentVideoTexture = pipeline.getVideoTexture();
|
|
115
108
|
}
|
|
116
|
-
|
|
109
|
+
if (!this._currentVideoTexture)
|
|
110
|
+
return undefined;
|
|
111
|
+
this._imageProcessor.uploadFrame(this._currentVideoTexture, this._video, rotation, this._isUserFacing);
|
|
117
112
|
this._isUploadFrame = !this._isUploadFrame;
|
|
118
113
|
return undefined;
|
|
119
114
|
}
|
|
120
|
-
if (currentlyProcessing)
|
|
115
|
+
if (currentlyProcessing || !this._currentVideoTexture)
|
|
121
116
|
return undefined;
|
|
122
117
|
this._isUploadFrame = !this._isUploadFrame;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
_uploadFrame(rotation, fc) {
|
|
126
|
-
if (!this._currentVideoTexture)
|
|
127
|
-
return;
|
|
128
|
-
let pipeline = pipeline_1.Pipeline.get(this._pipeline);
|
|
129
|
-
if (!pipeline)
|
|
130
|
-
return;
|
|
131
|
-
let gl = pipeline.glContext;
|
|
132
|
-
if (!gl)
|
|
133
|
-
return;
|
|
134
|
-
gl.disable(gl.SCISSOR_TEST);
|
|
135
|
-
gl.disable(gl.DEPTH_TEST);
|
|
136
|
-
gl.disable(gl.BLEND);
|
|
137
|
-
gl.disable(gl.CULL_FACE);
|
|
138
|
-
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
139
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
140
|
-
gl.bindTexture(gl.TEXTURE_2D, this._currentVideoTexture);
|
|
141
|
-
const level = 0;
|
|
142
|
-
const internalFormat = gl.RGBA;
|
|
143
|
-
const srcFormat = gl.RGBA;
|
|
144
|
-
const srcType = gl.UNSIGNED_BYTE;
|
|
145
|
-
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, srcFormat, srcType, this._video);
|
|
146
|
-
let videoWidth = 0;
|
|
147
|
-
let videoHeight = 0;
|
|
148
|
-
if (this._video instanceof HTMLVideoElement) {
|
|
149
|
-
videoWidth = this._video.videoWidth;
|
|
150
|
-
videoHeight = this._video.videoHeight;
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
videoWidth = this._video.width;
|
|
154
|
-
videoHeight = this._video.height;
|
|
155
|
-
}
|
|
156
|
-
if (videoHeight > videoWidth)
|
|
157
|
-
videoHeight = [videoWidth, videoWidth = videoHeight][0];
|
|
158
|
-
this._updateTransforms(rotation, fc);
|
|
159
|
-
let framebuffer = this._getFramebuffer(gl, profile_1.profile.dataWidth / 4, profile_1.profile.dataHeight);
|
|
160
|
-
let vbo = this._getVertexBuffer(gl);
|
|
161
|
-
let ibo = this._getIndexBuffer(gl);
|
|
162
|
-
let shader = this._getGreyscaleShader(gl);
|
|
163
|
-
// // Rendering to the greyscale conversion buffer - bind the framebuffer
|
|
164
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
|
165
|
-
gl.viewport(0, 0, this._framebufferWidth, this._framebufferHeight);
|
|
166
|
-
// // We'll be replacing all the content - clear is a good hint for this on mobile
|
|
167
|
-
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
|
168
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
169
|
-
// // Set up bindings for vertex attributes
|
|
170
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
171
|
-
gl.vertexAttribPointer(shader.aVertexPositionLoc, 2, gl.FLOAT, false, 4 * 4, 0);
|
|
172
|
-
gl.enableVertexAttribArray(shader.aVertexPositionLoc);
|
|
173
|
-
gl.vertexAttribPointer(shader.aTextureCoordLoc, 2, gl.FLOAT, false, 4 * 4, 2 * 4);
|
|
174
|
-
gl.enableVertexAttribArray(shader.aTextureCoordLoc);
|
|
175
|
-
// Bind the index buffer
|
|
176
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
177
|
-
// Tell WebGL to use our program when drawing
|
|
178
|
-
gl.useProgram(shader.program);
|
|
179
|
-
// Specify greyscale width for the correct offsets, and the uv transform
|
|
180
|
-
gl.uniform1f(shader.uTexWidthLoc, profile_1.profile.dataWidth);
|
|
181
|
-
gl.uniformMatrix4fv(shader.uUvTransformLoc, false, this._cameraUvTransform);
|
|
182
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
183
|
-
// Bind the texture to texture unit 0
|
|
184
|
-
gl.bindTexture(gl.TEXTURE_2D, this._currentVideoTexture);
|
|
185
|
-
// Tell the shader we bound the texture to texture unit 0
|
|
186
|
-
gl.uniform1i(shader.uSamplerLoc, 0);
|
|
187
|
-
// Do the drawing...
|
|
188
|
-
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
|
189
|
-
// Disable attribute arrays
|
|
190
|
-
gl.disableVertexAttribArray(shader.aVertexPositionLoc);
|
|
191
|
-
gl.disableVertexAttribArray(shader.aTextureCoordLoc);
|
|
192
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
193
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
194
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
195
|
-
gl.useProgram(null);
|
|
196
|
-
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
197
|
-
}
|
|
198
|
-
_readFrame(p, gl) {
|
|
199
|
-
if (!this._currentVideoTexture)
|
|
200
|
-
throw new Error("No video texture");
|
|
201
|
-
let tex = this._currentVideoTexture;
|
|
202
|
-
this._currentVideoTexture = undefined;
|
|
203
|
-
let greySize = profile_1.profile.dataWidth * profile_1.profile.dataHeight;
|
|
204
|
-
let pixels = p.cameraPixelArrays.pop();
|
|
118
|
+
let greySize = profile.dataWidth * profile.dataHeight;
|
|
119
|
+
let pixels = pipeline.cameraPixelArrays.pop();
|
|
205
120
|
while (pixels) {
|
|
206
121
|
if (pixels.byteLength === greySize)
|
|
207
122
|
break;
|
|
208
|
-
pixels =
|
|
123
|
+
pixels = pipeline.cameraPixelArrays.pop();
|
|
209
124
|
}
|
|
210
125
|
if (!pixels) {
|
|
211
126
|
pixels = new ArrayBuffer(greySize);
|
|
212
127
|
}
|
|
213
|
-
let
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
gl.readPixels(0, 0, this._framebufferWidth, this._framebufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixelsView);
|
|
217
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
218
|
-
let focalLength = 300.0 * profile_1.profile.dataWidth / 320.0;
|
|
128
|
+
let tex = this._currentVideoTexture;
|
|
129
|
+
this._currentVideoTexture = undefined;
|
|
130
|
+
let focalLength = 300.0 * profile.dataWidth / 320.0;
|
|
219
131
|
this._cameraModel[0] = focalLength;
|
|
220
132
|
this._cameraModel[1] = focalLength;
|
|
221
|
-
this._cameraModel[2] =
|
|
222
|
-
this._cameraModel[3] =
|
|
223
|
-
return {
|
|
224
|
-
uvTransform: this._cameraUvTransform,
|
|
225
|
-
data: pixels,
|
|
226
|
-
texture: tex,
|
|
227
|
-
cameraModel: this._cameraModel,
|
|
228
|
-
dataWidth: profile_1.profile.dataWidth,
|
|
229
|
-
dataHeight: profile_1.profile.dataHeight,
|
|
230
|
-
userFacing: this._computedFrontCameraRotation,
|
|
231
|
-
cameraToDevice: this._computedFrontCameraRotation ? this._cameraToDeviceTransformUserFacing : this._cameraToDeviceTransform,
|
|
232
|
-
cameraSource: this
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
_updateTransforms(rot, fc) {
|
|
236
|
-
if (rot == this._computedTransformRotation && fc == this._computedFrontCameraRotation)
|
|
237
|
-
return;
|
|
238
|
-
this._computedTransformRotation = rot;
|
|
239
|
-
this._computedFrontCameraRotation = fc;
|
|
240
|
-
this._cameraUvTransform = this._getCameraUvTransform();
|
|
241
|
-
}
|
|
242
|
-
_getCameraUvTransform() {
|
|
243
|
-
switch (this._computedTransformRotation) {
|
|
244
|
-
case 270: return new Float32Array([0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1]);
|
|
245
|
-
case 180: return new Float32Array([-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1]);
|
|
246
|
-
case 90: return new Float32Array([0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1]);
|
|
247
|
-
}
|
|
248
|
-
return new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
|
249
|
-
}
|
|
250
|
-
_getFramebuffer(gl, fbWidth, fbHeight) {
|
|
251
|
-
if (this._framebufferWidth === fbWidth && this._framebufferHeight === fbHeight && this._framebufferId)
|
|
252
|
-
return this._framebufferId;
|
|
253
|
-
if (this._framebufferId) {
|
|
254
|
-
gl.deleteFramebuffer(this._framebufferId);
|
|
255
|
-
this._framebufferId = null;
|
|
256
|
-
}
|
|
257
|
-
if (this._renderTexture) {
|
|
258
|
-
gl.deleteTexture(this._renderTexture);
|
|
259
|
-
this._renderTexture = null;
|
|
260
|
-
}
|
|
261
|
-
this._framebufferId = gl.createFramebuffer();
|
|
262
|
-
if (!this._framebufferId)
|
|
263
|
-
throw new Error("Unable to create framebuffer");
|
|
264
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebufferId);
|
|
265
|
-
this._renderTexture = gl.createTexture();
|
|
266
|
-
if (!this._renderTexture)
|
|
267
|
-
throw new Error("Unable to create render texture");
|
|
268
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
269
|
-
gl.bindTexture(gl.TEXTURE_2D, this._renderTexture);
|
|
270
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fbWidth, fbHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
271
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
272
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
273
|
-
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
274
|
-
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._renderTexture, 0);
|
|
275
|
-
let fbStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
276
|
-
if (fbStatus !== gl.FRAMEBUFFER_COMPLETE)
|
|
277
|
-
throw new Error("Framebuffer not complete: " + fbStatus.toString());
|
|
278
|
-
this._framebufferWidth = fbWidth;
|
|
279
|
-
this._framebufferHeight = fbHeight;
|
|
280
|
-
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
281
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
282
|
-
return this._framebufferId;
|
|
283
|
-
}
|
|
284
|
-
_getVertexBuffer(gl) {
|
|
285
|
-
if (this._vertexBuffer)
|
|
286
|
-
return this._vertexBuffer;
|
|
287
|
-
this._vertexBuffer = gl.createBuffer();
|
|
288
|
-
if (!this._vertexBuffer)
|
|
289
|
-
throw new Error("Unable to create vertex buffer");
|
|
290
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
|
|
291
|
-
let buffer = new Float32Array([-1.0, -1.0, 0.0, 0.0,
|
|
292
|
-
-1.0, 1.0, 0.0, 1.0,
|
|
293
|
-
1.0, 1.0, 1.0, 1.0,
|
|
294
|
-
1.0, -1.0, 1.0, 0.0]);
|
|
295
|
-
gl.bufferData(gl.ARRAY_BUFFER, buffer, gl.STATIC_DRAW);
|
|
296
|
-
return this._vertexBuffer;
|
|
297
|
-
}
|
|
298
|
-
_getIndexBuffer(gl) {
|
|
299
|
-
if (this._indexBuffer)
|
|
300
|
-
return this._indexBuffer;
|
|
301
|
-
this._indexBuffer = gl.createBuffer();
|
|
302
|
-
if (!this._indexBuffer)
|
|
303
|
-
throw new Error("Unable to create index buffer");
|
|
304
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
|
|
305
|
-
let buffer = new Uint16Array([0, 1, 2, 0, 2, 3]);
|
|
306
|
-
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, buffer, gl.STATIC_DRAW);
|
|
307
|
-
return this._indexBuffer;
|
|
308
|
-
}
|
|
309
|
-
_getGreyscaleShader(gl) {
|
|
310
|
-
if (this._greyscaleShader)
|
|
311
|
-
return this._greyscaleShader;
|
|
312
|
-
let prog = gl.createProgram();
|
|
313
|
-
if (!prog)
|
|
314
|
-
throw new Error("Unable to create program");
|
|
315
|
-
let vertexShader = shader_1.compileShader(gl, gl.VERTEX_SHADER, greyscaleVsSource);
|
|
316
|
-
let fragmentShader = shader_1.compileShader(gl, gl.FRAGMENT_SHADER, greyscaleFsSource);
|
|
317
|
-
gl.attachShader(prog, vertexShader);
|
|
318
|
-
gl.attachShader(prog, fragmentShader);
|
|
319
|
-
shader_1.linkProgram(gl, prog);
|
|
320
|
-
let uTexWidthLoc = gl.getUniformLocation(prog, "uTexWidth");
|
|
321
|
-
if (!uTexWidthLoc)
|
|
322
|
-
throw new Error("Unable to get uniform location uTexWidth");
|
|
323
|
-
let uUvTransformLoc = gl.getUniformLocation(prog, "uUvTransform");
|
|
324
|
-
if (!uUvTransformLoc)
|
|
325
|
-
throw new Error("Unable to get uniform location uUvTransform");
|
|
326
|
-
let uSamplerLoc = gl.getUniformLocation(prog, "uSampler");
|
|
327
|
-
if (!uSamplerLoc)
|
|
328
|
-
throw new Error("Unable to get uniform location uSampler");
|
|
329
|
-
this._greyscaleShader = {
|
|
330
|
-
program: prog,
|
|
331
|
-
aVertexPositionLoc: gl.getAttribLocation(prog, "aVertexPosition"),
|
|
332
|
-
aTextureCoordLoc: gl.getAttribLocation(prog, "aTextureCoord"),
|
|
333
|
-
uTexWidthLoc: uTexWidthLoc,
|
|
334
|
-
uUvTransformLoc: uUvTransformLoc,
|
|
335
|
-
uSamplerLoc: uSamplerLoc
|
|
336
|
-
};
|
|
337
|
-
return this._greyscaleShader;
|
|
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) });
|
|
338
136
|
}
|
|
339
137
|
uploadGL() {
|
|
340
138
|
// No-op as already uploaded
|
|
341
139
|
}
|
|
342
140
|
}
|
|
343
|
-
exports.HTMLElementSource = HTMLElementSource;
|
|
344
|
-
let greyscaleVsSource = `
|
|
345
|
-
attribute vec4 aVertexPosition;
|
|
346
|
-
attribute vec2 aTextureCoord;
|
|
347
|
-
|
|
348
|
-
varying highp vec2 vTextureCoord1;
|
|
349
|
-
varying highp vec2 vTextureCoord2;
|
|
350
|
-
varying highp vec2 vTextureCoord3;
|
|
351
|
-
varying highp vec2 vTextureCoord4;
|
|
352
|
-
|
|
353
|
-
uniform float uTexWidth;
|
|
354
|
-
uniform mat4 uUvTransform;
|
|
355
|
-
|
|
356
|
-
void main(void) {
|
|
357
|
-
highp vec2 offset1 = vec2(1.5 / uTexWidth, 0);
|
|
358
|
-
highp vec2 offset2 = vec2(0.5 / uTexWidth, 0);
|
|
359
|
-
|
|
360
|
-
gl_Position = aVertexPosition;
|
|
361
|
-
vTextureCoord1 = (uUvTransform * vec4(aTextureCoord - offset1, 0, 1)).xy;
|
|
362
|
-
vTextureCoord2 = (uUvTransform * vec4(aTextureCoord - offset2, 0, 1)).xy;
|
|
363
|
-
vTextureCoord3 = (uUvTransform * vec4(aTextureCoord + offset2, 0, 1)).xy;
|
|
364
|
-
vTextureCoord4 = (uUvTransform * vec4(aTextureCoord + offset1, 0, 1)).xy;
|
|
365
|
-
}
|
|
366
|
-
`;
|
|
367
|
-
// Fragment shader program
|
|
368
|
-
let greyscaleFsSource = `
|
|
369
|
-
varying highp vec2 vTextureCoord1;
|
|
370
|
-
varying highp vec2 vTextureCoord2;
|
|
371
|
-
varying highp vec2 vTextureCoord3;
|
|
372
|
-
varying highp vec2 vTextureCoord4;
|
|
373
|
-
|
|
374
|
-
uniform sampler2D uSampler;
|
|
375
|
-
|
|
376
|
-
const lowp vec3 colorWeights = vec3(77.0 / 256.0, 150.0 / 256.0, 29.0 / 256.0);
|
|
377
|
-
|
|
378
|
-
void main(void) {
|
|
379
|
-
lowp vec4 outpx;
|
|
380
|
-
|
|
381
|
-
outpx.r = dot(colorWeights, texture2D(uSampler, vTextureCoord1).xyz);
|
|
382
|
-
outpx.g = dot(colorWeights, texture2D(uSampler, vTextureCoord2).xyz);
|
|
383
|
-
outpx.b = dot(colorWeights, texture2D(uSampler, vTextureCoord3).xyz);
|
|
384
|
-
outpx.a = dot(colorWeights, texture2D(uSampler, vTextureCoord4).xyz);
|
|
385
|
-
|
|
386
|
-
gl_FragColor = outpx;
|
|
387
|
-
}
|
|
388
|
-
`;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface ProcessedFrame {
|
|
2
|
+
data?: ArrayBuffer;
|
|
3
|
+
texture: WebGLTexture | undefined;
|
|
4
|
+
dataWidth: number;
|
|
5
|
+
dataHeight: number;
|
|
6
|
+
uvTransform?: Float32Array;
|
|
7
|
+
userFacing: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class ImageProcessGL {
|
|
10
|
+
private _gl;
|
|
11
|
+
protected _isPaused: boolean;
|
|
12
|
+
protected _hadFrames: boolean;
|
|
13
|
+
protected _isUserFacing: boolean;
|
|
14
|
+
protected _cameraToScreenRotation: number;
|
|
15
|
+
private _isUploadFrame;
|
|
16
|
+
private _computedTransformRotation;
|
|
17
|
+
private _computedFrontCameraRotation;
|
|
18
|
+
private _cameraUvTransform;
|
|
19
|
+
private _framebufferWidth;
|
|
20
|
+
private _framebufferHeight;
|
|
21
|
+
private _framebufferId;
|
|
22
|
+
private _renderTexture;
|
|
23
|
+
private _vertexBuffer;
|
|
24
|
+
private _indexBuffer;
|
|
25
|
+
private _greyscaleShader;
|
|
26
|
+
constructor(_gl: WebGLRenderingContext);
|
|
27
|
+
resetGLContext(): void;
|
|
28
|
+
destroy(): void;
|
|
29
|
+
uploadFrame(texture: WebGLTexture, img: HTMLVideoElement | HTMLImageElement | ImageBitmap, rotation: number, fc: boolean): void;
|
|
30
|
+
readFrame(texture: WebGLTexture, pixels: ArrayBuffer): ProcessedFrame;
|
|
31
|
+
private _updateTransforms;
|
|
32
|
+
private _getCameraUvTransform;
|
|
33
|
+
private _getFramebuffer;
|
|
34
|
+
private _getVertexBuffer;
|
|
35
|
+
private _getIndexBuffer;
|
|
36
|
+
private _getGreyscaleShader;
|
|
37
|
+
}
|