@webex/ladon-ts 4.0.0 → 4.2.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 +41 -9
- package/LICENSE +5 -5
- package/README.md +36 -36
- package/build/module/index.d.ts +6 -6
- package/build/module/index.js +6 -6
- package/build/module/lib/config.d.ts +67 -61
- package/build/module/lib/config.js +123 -109
- package/build/module/lib/generator.d.ts +62 -52
- package/build/module/lib/generator.js +233 -202
- package/build/module/lib/pipeline.d.ts +21 -21
- package/build/module/lib/pipeline.js +92 -83
- package/build/module/lib/renderer/blur-renderer.d.ts +21 -0
- package/build/module/lib/renderer/blur-renderer.js +190 -0
- package/build/module/lib/renderer/ladon-renderer.d.ts +6 -0
- package/build/module/lib/renderer/ladon-renderer.js +2 -0
- package/build/module/lib/renderer/passthrough-renderer.d.ts +14 -0
- package/build/module/lib/renderer/passthrough-renderer.js +57 -0
- package/build/module/lib/renderer/replacement-renderer.d.ts +16 -0
- package/build/module/lib/renderer/replacement-renderer.js +103 -0
- package/build/module/lib/renderer/webgl-renderer.d.ts +17 -0
- package/build/module/lib/renderer/webgl-renderer.js +113 -0
- package/build/module/lib/renderer.d.ts +5 -63
- package/build/module/lib/renderer.js +6 -463
- package/build/module/lib/util.d.ts +31 -1
- package/build/module/lib/util.js +101 -10
- package/build/module/lib/version.d.ts +1 -1
- package/build/module/lib/version.js +1 -1
- package/build/module/lib/worker/segmentation.d.ts +1 -0
- package/build/module/lib/worker/segmentation.js +42 -0
- package/package.json +76 -81
|
@@ -1,83 +1,92 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { LocalGenerator, NullGenerator, WorkerGenerator
|
|
11
|
-
import { BlurRenderer, PassthroughRenderer, ReplacementRenderer
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { LocalGenerator, NullGenerator, WorkerGenerator } from './generator';
|
|
11
|
+
import { BlurRenderer, PassthroughRenderer, ReplacementRenderer } from './renderer';
|
|
12
|
+
import { resizeImage } from './util';
|
|
13
|
+
export class Pipeline {
|
|
14
|
+
constructor(input_canvas, output_canvas, config) {
|
|
15
|
+
this.input_canvas = input_canvas;
|
|
16
|
+
this.output_canvas = output_canvas;
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.loaded = false;
|
|
19
|
+
const input_ctx = this.input_canvas.getContext('2d', {
|
|
20
|
+
alpha: false,
|
|
21
|
+
willReadFrequently: true,
|
|
22
|
+
});
|
|
23
|
+
if (!input_ctx) {
|
|
24
|
+
throw new Error('[ladon-ts] - error getting input context 2d');
|
|
25
|
+
}
|
|
26
|
+
this.input_ctx = input_ctx;
|
|
27
|
+
}
|
|
28
|
+
onFrame() {
|
|
29
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
if (!this.generator || !this.renderer) {
|
|
31
|
+
throw new Error('[ladon-ts] - pipeline is not loaded.');
|
|
32
|
+
}
|
|
33
|
+
const rawImageData = this.input_ctx.getImageData(0, 0, this.config.input.width, this.config.input.height).data;
|
|
34
|
+
let maskImageData = rawImageData;
|
|
35
|
+
// Resize the image data if the model expects a fixed size input (e.g., tiny model).
|
|
36
|
+
if (this.config.mask.input_size.width !== this.config.input.width) {
|
|
37
|
+
maskImageData = resizeImage(rawImageData, this.config.input.width, this.config.input.height, this.config.mask.input_size.width, this.config.mask.input_size.height);
|
|
38
|
+
}
|
|
39
|
+
const mask = yield this.generator.getMask(maskImageData);
|
|
40
|
+
// Render the full size video image in the background with the mask on top.
|
|
41
|
+
yield this.renderer.render(rawImageData, mask);
|
|
42
|
+
// Cleanup the mask data.
|
|
43
|
+
yield this.generator.postRender(maskImageData);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
isLoaded() {
|
|
47
|
+
return this.loaded;
|
|
48
|
+
}
|
|
49
|
+
load() {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
switch (this.config.render.type) {
|
|
52
|
+
case 'blur':
|
|
53
|
+
this.renderer = new BlurRenderer(this.output_canvas, this.config);
|
|
54
|
+
break;
|
|
55
|
+
case 'passthrough':
|
|
56
|
+
this.renderer = new PassthroughRenderer(this.output_canvas, this.config);
|
|
57
|
+
break;
|
|
58
|
+
case 'replacement':
|
|
59
|
+
this.renderer = new ReplacementRenderer(this.output_canvas, this.config);
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
throw new Error('[ladon-ts] - renderer not implemented.');
|
|
63
|
+
}
|
|
64
|
+
yield this.renderer.load();
|
|
65
|
+
if (this.config.render.type === 'passthrough') {
|
|
66
|
+
// automatically disable model evaluation when the renderer is set to passthrough
|
|
67
|
+
// Note: this may change when gestures are detected (model eval will be a dependency for more than rendering)
|
|
68
|
+
this.generator = new NullGenerator(this.config);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
switch (this.config.mask.generator) {
|
|
72
|
+
case 'local':
|
|
73
|
+
this.generator = new LocalGenerator(this.config);
|
|
74
|
+
break;
|
|
75
|
+
case 'worker':
|
|
76
|
+
this.generator = new WorkerGenerator(this.config);
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
throw new Error('[ladon-ts] - generator not implemented.');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
yield this.generator.load();
|
|
83
|
+
this.loaded = true;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
destroy() {
|
|
87
|
+
var _a, _b;
|
|
88
|
+
(_a = this.generator) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
89
|
+
(_b = this.renderer) === null || _b === void 0 ? void 0 : _b.destroy();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3BpcGVsaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUNBLE9BQU8sRUFBRSxjQUFjLEVBQWlCLGFBQWEsRUFBRSxlQUFlLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUYsT0FBTyxFQUFFLFlBQVksRUFBaUIsbUJBQW1CLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDbkcsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQVNyQyxNQUFNLE9BQU8sUUFBUTtJQU9qQixZQUNZLFlBQStCLEVBQy9CLGFBQWdDLEVBQ3hCLE1BQXNCO1FBRjlCLGlCQUFZLEdBQVosWUFBWSxDQUFtQjtRQUMvQixrQkFBYSxHQUFiLGFBQWEsQ0FBbUI7UUFDeEIsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUFQbEMsV0FBTSxHQUFHLEtBQUssQ0FBQztRQVNuQixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUU7WUFDakQsS0FBSyxFQUFFLEtBQUs7WUFDWixrQkFBa0IsRUFBRSxJQUFJO1NBQzNCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7U0FDbEU7UUFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztJQUMvQixDQUFDO0lBRVksT0FBTzs7WUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7YUFDM0Q7WUFFRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FDNUMsQ0FBQyxFQUNELENBQUMsRUFDRCxJQUFJ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
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PipelineConfig } from '../config';
|
|
2
|
+
import { MaskResult } from '../generator';
|
|
3
|
+
import { LadonRenderer } from './ladon-renderer';
|
|
4
|
+
import { WebGLRenderer } from './webgl-renderer';
|
|
5
|
+
export declare class BlurRenderer extends WebGLRenderer implements LadonRenderer {
|
|
6
|
+
output_canvas: HTMLCanvasElement;
|
|
7
|
+
readonly config: PipelineConfig;
|
|
8
|
+
private program_1;
|
|
9
|
+
private program_2;
|
|
10
|
+
private framebuffer;
|
|
11
|
+
private transfer_texture;
|
|
12
|
+
private u_blur;
|
|
13
|
+
private fragment_shader_common;
|
|
14
|
+
private fragment_shader_pass_1_src;
|
|
15
|
+
fragment_shader_pass_2_src: string;
|
|
16
|
+
constructor(output_canvas: HTMLCanvasElement, config: PipelineConfig);
|
|
17
|
+
render(input: Uint8ClampedArray, mask: MaskResult): Promise<void>;
|
|
18
|
+
load(): Promise<void>;
|
|
19
|
+
destroy(): void;
|
|
20
|
+
private getBlurKernel;
|
|
21
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { compileShader, linkProgram } from '../util';
|
|
11
|
+
import { WebGLRenderer } from './webgl-renderer';
|
|
12
|
+
export class BlurRenderer extends WebGLRenderer {
|
|
13
|
+
constructor(output_canvas, config) {
|
|
14
|
+
super(output_canvas, config);
|
|
15
|
+
this.output_canvas = output_canvas;
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.fragment_shader_common = `#version 300 es
|
|
18
|
+
precision highp float;
|
|
19
|
+
|
|
20
|
+
#define KERNEL_SIZE ${this.config.render.kernel_size}
|
|
21
|
+
#define HORIZONTAL vec2(1.0, 0.0)
|
|
22
|
+
#define VERTICAL vec2(0.0, 1.0)
|
|
23
|
+
#define EPSILON 0.00001
|
|
24
|
+
|
|
25
|
+
out vec4 outColor;
|
|
26
|
+
|
|
27
|
+
uniform sampler2D u_image;
|
|
28
|
+
uniform float u_kernel[KERNEL_SIZE];
|
|
29
|
+
uniform sampler2D u_mask;
|
|
30
|
+
uniform vec2 u_resolution;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
float get_mask(vec2 st) {
|
|
34
|
+
return clamp(texture(u_mask, st).r, 0.0, 1.0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
float get_inv_mask(vec2 st) {
|
|
38
|
+
return 1.0 - get_mask(st);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
vec4 get_offset_mul(sampler2D src, vec2 uv, float weight) {
|
|
42
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
|
43
|
+
return vec4(vec3(0.0), weight);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 4th channel is masked weight value
|
|
47
|
+
return vec4(vec3(texture(src, uv).rgb * get_inv_mask(uv) * weight), get_mask(uv) * weight);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
vec3 blur(sampler2D src, vec2 uv, vec2 direction) {
|
|
51
|
+
vec4 result = vec4(0.0);
|
|
52
|
+
|
|
53
|
+
vec2 step = (direction / u_resolution);
|
|
54
|
+
int offset = (KERNEL_SIZE - 1) / 2;
|
|
55
|
+
|
|
56
|
+
for (int i = 0; i < KERNEL_SIZE; i++) {
|
|
57
|
+
vec2 offset = step * float(i - offset);
|
|
58
|
+
result += get_offset_mul(src, uv + offset, u_kernel[i]);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (abs(result.a - 1.0) < EPSILON) {
|
|
62
|
+
return vec3(0.0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// redistribute weights from masked areas
|
|
66
|
+
return result.rgb * (1.0 + (result.a / (1.0 - result.a)));
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
this.fragment_shader_pass_1_src = this.fragment_shader_common +
|
|
70
|
+
`
|
|
71
|
+
void main() {
|
|
72
|
+
vec2 st = gl_FragCoord.xy / u_resolution;
|
|
73
|
+
|
|
74
|
+
outColor = vec4(blur(u_image, st, HORIZONTAL) * get_inv_mask(st), 1.0);
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
this.fragment_shader_pass_2_src = this.fragment_shader_common +
|
|
78
|
+
`
|
|
79
|
+
uniform sampler2D u_blur;
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
void main() {
|
|
83
|
+
${this.getUVCalculation()}
|
|
84
|
+
|
|
85
|
+
vec3 blurred = blur(u_blur, st, VERTICAL);
|
|
86
|
+
vec3 image = texture(u_image, st).rgb;
|
|
87
|
+
float mask = texture(u_mask, st).r;
|
|
88
|
+
|
|
89
|
+
outColor = vec4(blurred * (1.0 - mask) + image * mask, 1.0);
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
if (this.config.render.kernel_size % 2 === 0) {
|
|
93
|
+
throw new Error('[ladon-ts] - kernel_size must be odd');
|
|
94
|
+
}
|
|
95
|
+
// program pass 1 setup
|
|
96
|
+
{
|
|
97
|
+
const vertex_shader = compileShader(this.gl, this.gl.VERTEX_SHADER, this.vertex_shader_src);
|
|
98
|
+
const fragment_shader = compileShader(this.gl, this.gl.FRAGMENT_SHADER, this.fragment_shader_pass_1_src);
|
|
99
|
+
this.program_1 = linkProgram(this.gl, vertex_shader, fragment_shader);
|
|
100
|
+
this.gl.useProgram(this.program_1);
|
|
101
|
+
const framebuffer = this.gl.createFramebuffer();
|
|
102
|
+
if (!framebuffer) {
|
|
103
|
+
throw new Error('[ladon-ts] - error creating framebuffer');
|
|
104
|
+
}
|
|
105
|
+
this.framebuffer = framebuffer;
|
|
106
|
+
const transfer_texture = this.gl.createTexture();
|
|
107
|
+
if (!transfer_texture) {
|
|
108
|
+
throw new Error('[ladon-ts] - error creating output texture');
|
|
109
|
+
}
|
|
110
|
+
this.transfer_texture = transfer_texture;
|
|
111
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);
|
|
112
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture);
|
|
113
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
114
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
115
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
116
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.config.input.width, this.config.input.height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);
|
|
117
|
+
this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this.transfer_texture, 0);
|
|
118
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
119
|
+
this.setSharedUniforms(this.program_1);
|
|
120
|
+
const u_kernel = this.gl.getUniformLocation(this.program_1, 'u_kernel');
|
|
121
|
+
if (!u_kernel) {
|
|
122
|
+
throw new Error('[ladon-ts] - error finding "u_kernel" uniform');
|
|
123
|
+
}
|
|
124
|
+
this.gl.uniform1fv(u_kernel, this.getBlurKernel());
|
|
125
|
+
}
|
|
126
|
+
// program pass 2 setup
|
|
127
|
+
{
|
|
128
|
+
const vertex_shader = compileShader(this.gl, this.gl.VERTEX_SHADER, this.vertex_shader_src);
|
|
129
|
+
const fragment_shader = compileShader(this.gl, this.gl.FRAGMENT_SHADER, this.fragment_shader_pass_2_src);
|
|
130
|
+
this.program_2 = linkProgram(this.gl, vertex_shader, fragment_shader);
|
|
131
|
+
this.gl.useProgram(this.program_2);
|
|
132
|
+
const u_blur = this.gl.getUniformLocation(this.program_2, 'u_blur');
|
|
133
|
+
if (!u_blur) {
|
|
134
|
+
throw new Error('[ladon-ts] - error finding "u_blur" uniform');
|
|
135
|
+
}
|
|
136
|
+
this.u_blur = u_blur;
|
|
137
|
+
this.gl.activeTexture(this.gl.TEXTURE2);
|
|
138
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture);
|
|
139
|
+
this.gl.uniform1i(this.u_blur, 2);
|
|
140
|
+
this.setSharedUniforms(this.program_2);
|
|
141
|
+
const u_kernel = this.gl.getUniformLocation(this.program_2, 'u_kernel');
|
|
142
|
+
if (!u_kernel) {
|
|
143
|
+
throw new Error('[ladon-ts] - error finding "u_kernel" uniform');
|
|
144
|
+
}
|
|
145
|
+
this.gl.uniform1fv(u_kernel, this.getBlurKernel());
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
render(input, mask) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
this.uploadVideoStream(input);
|
|
151
|
+
if (mask.warm) {
|
|
152
|
+
this.gl.activeTexture(this.gl.TEXTURE1);
|
|
153
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.mask_texture);
|
|
154
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R32F, this.config.mask.output_size.width, this.config.mask.output_size.height, 0, this.gl.RED, this.gl.FLOAT, mask.data);
|
|
155
|
+
}
|
|
156
|
+
// program pass 1 - blur in one direction & output to framebuffer
|
|
157
|
+
this.gl.useProgram(this.program_1);
|
|
158
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);
|
|
159
|
+
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);
|
|
160
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
161
|
+
// program pass 2 - blur in other direction & draw to screen
|
|
162
|
+
this.gl.useProgram(this.program_2);
|
|
163
|
+
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);
|
|
164
|
+
this.postDraw();
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
load() {
|
|
168
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
169
|
+
// empty
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
destroy() {
|
|
173
|
+
// empty
|
|
174
|
+
}
|
|
175
|
+
getBlurKernel() {
|
|
176
|
+
const kernel = [];
|
|
177
|
+
let sum = 0;
|
|
178
|
+
for (let i = 0; i < this.config.render.kernel_size; i++) {
|
|
179
|
+
let w = i - (this.config.render.kernel_size - 1) / 2;
|
|
180
|
+
w = Math.exp(-(Math.pow(w, 2)) / Math.pow(this.config.render.sigma, 2));
|
|
181
|
+
kernel.push(w);
|
|
182
|
+
sum += w;
|
|
183
|
+
}
|
|
184
|
+
for (let i = 0; i < this.config.render.kernel_size; i++) {
|
|
185
|
+
kernel[i] = kernel[i] / sum;
|
|
186
|
+
}
|
|
187
|
+
return new Float32Array(kernel);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmx1ci1yZW5kZXJlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcmVuZGVyZXIvYmx1ci1yZW5kZXJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFFQSxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUdyRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFakQsTUFBTSxPQUFPLFlBQWEsU0FBUSxhQUFhO0lBeUYzQyxZQUFtQixhQUFnQyxFQUFrQixNQUFzQjtRQUN2RixLQUFLLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRGQsa0JBQWEsR0FBYixhQUFhLENBQW1CO1FBQWtCLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBaEZuRiwyQkFBc0IsR0FBRzs7OzBCQUdWLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBcUIsQ0FBQyxXQUFXOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FnRHZFLENBQUM7UUFFVSwrQkFBMEIsR0FDOUIsSUFBSSxDQUFDLHNCQUFzQjtZQUMzQjs7Ozs7O0NBTVAsQ0FBQztRQUVTLCtCQUEwQixHQUM3QixJQUFJLENBQUMsc0JBQXNCO1lBQzNCOzs7OztNQUtGLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTs7Ozs7Ozs7Q0FRNUIsQ0FBQztRQUtNLElBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFxQixDQUFDLFdBQVcsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztTQUMzRDtRQUVELHVCQUF1QjtRQUN2QjtZQUNJLE1BQU0sYUFBYSxHQUFHLGFBQWEsQ0FDL0IsSUFBSSxDQUFDLEVBQUUsRUFDUCxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFDckIsSUFBSSxDQUFDLGlCQUFp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
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PipelineConfig } from '../config';
|
|
2
|
+
import { MaskResult } from '../generator';
|
|
3
|
+
import { LadonRenderer } from './ladon-renderer';
|
|
4
|
+
import { WebGLRenderer } from './webgl-renderer';
|
|
5
|
+
export declare class PassthroughRenderer extends WebGLRenderer implements LadonRenderer {
|
|
6
|
+
output_canvas: HTMLCanvasElement;
|
|
7
|
+
readonly config: PipelineConfig;
|
|
8
|
+
private program;
|
|
9
|
+
private fragment_shader;
|
|
10
|
+
constructor(output_canvas: HTMLCanvasElement, config: PipelineConfig);
|
|
11
|
+
render(input: Uint8ClampedArray, _: MaskResult): Promise<void>;
|
|
12
|
+
load(): Promise<void>;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { compileShader, linkProgram } from '../util';
|
|
11
|
+
import { WebGLRenderer } from './webgl-renderer';
|
|
12
|
+
export class PassthroughRenderer extends WebGLRenderer {
|
|
13
|
+
constructor(output_canvas, config) {
|
|
14
|
+
super(output_canvas, config);
|
|
15
|
+
this.output_canvas = output_canvas;
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.fragment_shader = `#version 300 es
|
|
18
|
+
precision highp float;
|
|
19
|
+
|
|
20
|
+
out vec4 outColor;
|
|
21
|
+
|
|
22
|
+
uniform sampler2D u_image;
|
|
23
|
+
uniform vec2 u_resolution;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
void main() {
|
|
27
|
+
${this.getUVCalculation()}
|
|
28
|
+
|
|
29
|
+
outColor = vec4(texture(u_image, st).rgb, 1.0);
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
const vertex_shader = compileShader(this.gl, this.gl.VERTEX_SHADER, this.vertex_shader_src);
|
|
33
|
+
const fragment_shader = compileShader(this.gl, this.gl.FRAGMENT_SHADER, this.fragment_shader);
|
|
34
|
+
this.program = linkProgram(this.gl, vertex_shader, fragment_shader);
|
|
35
|
+
this.gl.useProgram(this.program);
|
|
36
|
+
this.setSharedUniforms(this.program);
|
|
37
|
+
}
|
|
38
|
+
render(input,
|
|
39
|
+
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
|
40
|
+
_) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
this.uploadVideoStream(input);
|
|
43
|
+
this.gl.useProgram(this.program);
|
|
44
|
+
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);
|
|
45
|
+
this.postDraw();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
load() {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
// empty
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
destroy() {
|
|
54
|
+
// empty
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3Rocm91Z2gtcmVuZGVyZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3JlbmRlcmVyL3Bhc3N0aHJvdWdoLXJlbmRlcmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUVBLE9BQU8sRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBR3JELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVqRCxNQUFNLE9BQU8sbUJBQW9CLFNBQVEsYUFBYTtJQW1CbEQsWUFBbUIsYUFBZ0MsRUFBa0IsTUFBc0I7UUFDdkYsS0FBSyxDQUFDLGFBQWEsRUFBRSxNQUFNLENBQUMsQ0FBQztRQURkLGtCQUFhLEdBQWIsYUFBYSxDQUFtQjtRQUFrQixXQUFNLEdBQU4sTUFBTSxDQUFnQjtRQWhCbkYsb0JBQWUsR0FBRzs7Ozs7Ozs7OztNQVV4QixJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Ozs7Q0FJNUIsQ0FBQztRQUtNLE1BQU0sYUFBYSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzVGLE1BQU0sZUFBZSxHQUFHLGFBQWEsQ0FDakMsSUFBSSxDQUFDLEVBQUUsRUFDUCxJQUFJLENBQUMsRUFBRSxDQUFDLGVBQWUsRUFDdkIsSUFBSSxDQUFDLGVBQWUsQ0FDdkIsQ0FBQztRQUVGLElBQUksQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsYUFBYSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3BFLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFWSxNQUFNLENBQ2YsS0FBd0I7SUFDeEIsZ0VBQWdFO0lBQ2hFLENBQWE7O1lBRWIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRTlCLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUVqQyxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFFaEUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3BCLENBQUM7S0FBQTtJQUVZLElBQUk7O1lBQ2IsUUFBUTtRQUNaLENBQUM7S0FBQTtJQUVNLE9BQU87UUFDVixRQUFRO0lBQ1osQ0FBQztDQUNKIn0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PipelineConfig } from '../config';
|
|
2
|
+
import { MaskResult } from '../generator';
|
|
3
|
+
import { LadonRenderer } from './ladon-renderer';
|
|
4
|
+
import { WebGLRenderer } from './webgl-renderer';
|
|
5
|
+
export declare class ReplacementRenderer extends WebGLRenderer implements LadonRenderer {
|
|
6
|
+
output_canvas: HTMLCanvasElement;
|
|
7
|
+
readonly config: PipelineConfig;
|
|
8
|
+
private program;
|
|
9
|
+
private background_canvas_ctx;
|
|
10
|
+
protected background_texture: WebGLTexture;
|
|
11
|
+
private fragment_shader;
|
|
12
|
+
constructor(output_canvas: HTMLCanvasElement, config: PipelineConfig);
|
|
13
|
+
render(input: Uint8ClampedArray, mask: MaskResult): Promise<void>;
|
|
14
|
+
load(): Promise<void>;
|
|
15
|
+
destroy(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { compileShader, linkProgram } from '../util';
|
|
11
|
+
import { WebGLRenderer } from './webgl-renderer';
|
|
12
|
+
export class ReplacementRenderer extends WebGLRenderer {
|
|
13
|
+
constructor(output_canvas, config) {
|
|
14
|
+
super(output_canvas, config);
|
|
15
|
+
this.output_canvas = output_canvas;
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.fragment_shader = `#version 300 es
|
|
18
|
+
precision highp float;
|
|
19
|
+
|
|
20
|
+
out vec4 outColor;
|
|
21
|
+
|
|
22
|
+
uniform sampler2D u_background;
|
|
23
|
+
uniform sampler2D u_image;
|
|
24
|
+
uniform sampler2D u_mask;
|
|
25
|
+
uniform vec2 u_resolution;
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
float get_mask(vec2 st) {
|
|
29
|
+
return clamp(texture(u_mask, st).r, 0.0, 1.0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
float get_inv_mask(vec2 st) {
|
|
33
|
+
return 1.0 - get_mask(st);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void main() {
|
|
37
|
+
${this.getUVCalculation()}
|
|
38
|
+
|
|
39
|
+
outColor = vec4(texture(u_background, st).rgb * get_inv_mask(st) + texture(u_image, st).rgb * get_mask(st), 1.0);
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
const background_canvas_ctx = this.config.render.background.getContext('2d');
|
|
43
|
+
if (!background_canvas_ctx) {
|
|
44
|
+
throw new Error('[ladon-ts] - could not get background canvas context 2d');
|
|
45
|
+
}
|
|
46
|
+
this.background_canvas_ctx = background_canvas_ctx;
|
|
47
|
+
const background_data = this.background_canvas_ctx.getImageData(0, 0, this.config.render.background.width, this.config.render.background.height).data;
|
|
48
|
+
if (this.config.render.kernel_size % 2 === 0) {
|
|
49
|
+
throw new Error('[ladon-ts] - kernel_size must be odd');
|
|
50
|
+
}
|
|
51
|
+
const vertex_shader = compileShader(this.gl, this.gl.VERTEX_SHADER, this.vertex_shader_src);
|
|
52
|
+
const fragment_shader = compileShader(this.gl, this.gl.FRAGMENT_SHADER, this.fragment_shader);
|
|
53
|
+
this.program = linkProgram(this.gl, vertex_shader, fragment_shader);
|
|
54
|
+
this.gl.useProgram(this.program);
|
|
55
|
+
this.setSharedUniforms(this.program);
|
|
56
|
+
const background_texture = this.gl.createTexture();
|
|
57
|
+
if (!background_texture) {
|
|
58
|
+
throw new Error('[ladon-ts] - error creating input texture');
|
|
59
|
+
}
|
|
60
|
+
this.background_texture = background_texture;
|
|
61
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.background_texture);
|
|
62
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
63
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
64
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
65
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.config.render.background.width, this.config.render.background.height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, background_data);
|
|
66
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, null);
|
|
67
|
+
const u_background = this.gl.getUniformLocation(this.program, 'u_background');
|
|
68
|
+
if (!u_background) {
|
|
69
|
+
throw new Error('[ladon-ts] - error finding "u_background" uniform');
|
|
70
|
+
}
|
|
71
|
+
this.gl.activeTexture(this.gl.TEXTURE2);
|
|
72
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.background_texture);
|
|
73
|
+
this.gl.uniform1i(u_background, 2);
|
|
74
|
+
}
|
|
75
|
+
render(input, mask) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
this.uploadVideoStream(input);
|
|
78
|
+
if (mask.warm) {
|
|
79
|
+
this.gl.activeTexture(this.gl.TEXTURE1);
|
|
80
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.mask_texture);
|
|
81
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.R32F, this.config.input.width, this.config.input.height, 0, this.gl.RED, this.gl.FLOAT, mask.data);
|
|
82
|
+
}
|
|
83
|
+
if (!this.config.render.static) {
|
|
84
|
+
const background_data = this.background_canvas_ctx.getImageData(0, 0, this.config.render.background.width, this.config.render.background.height).data;
|
|
85
|
+
this.gl.activeTexture(this.gl.TEXTURE2);
|
|
86
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.background_texture);
|
|
87
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.config.input.width, this.config.input.height, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, background_data);
|
|
88
|
+
}
|
|
89
|
+
this.gl.useProgram(this.program);
|
|
90
|
+
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);
|
|
91
|
+
this.postDraw();
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
load() {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
// empty
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
destroy() {
|
|
100
|
+
// empty
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwbGFjZW1lbnQtcmVuZGVyZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3JlbmRlcmVyL3JlcGxhY2VtZW50LXJlbmRlcmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUVBLE9BQU8sRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBR3JELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVqRCxNQUFNLE9BQU8sbUJBQW9CLFNBQVEsYUFBYTtJQWdDbEQsWUFBbUIsYUFBZ0MsRUFBa0IsTUFBc0I7UUFDdkYsS0FBSyxDQUFDLGFBQWEsRUFBRSxNQUFNLENBQUMsQ0FBQztRQURkLGtCQUFhLEdBQWIsYUFBYSxDQUFtQjtRQUFrQixXQUFNLEdBQU4sTUFBTSxDQUFnQjtRQTFCbkYsb0JBQWUsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7TUFvQnhCLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTs7OztDQUk1QixDQUFDO1FBS00sTUFBTSxxQkFBcUIsR0FDdkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUNmLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMscUJBQXFCLEVBQUU7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO1NBQzlFO1FBQ0QsSUFBSSxDQUFDLHFCQUFxQixHQUFHLHFCQUFxQixDQUFDO1FBQ25ELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxZQUFZLENBQzNELENBQUMsRUFDRCxDQUFDLEVBQ0EsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUE0QixDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQ3pELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBNEIsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUM5RCxDQUFDLElBQUksQ0FBQztRQUVQLElBQUss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
|