mirror of https://github.com/vladmandic/human
minor optimization to imagefx
parent
96a2fc787b
commit
00d525b207
|
@ -407,8 +407,8 @@ result = {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
performance = { // performance data of last execution for each module measuredin miliseconds
|
performance = { // performance data of last execution for each module measuredin miliseconds
|
||||||
backend, // time to initialize tf backend
|
backend, // time to initialize tf backend, valid only during backend startup
|
||||||
load, // time to load models
|
load, // time to load models, valid only during model load
|
||||||
image, // time for image processing
|
image, // time for image processing
|
||||||
body, // model time
|
body, // model time
|
||||||
hand, // model time
|
hand, // model time
|
||||||
|
|
|
@ -5019,19 +5019,19 @@ var require_imagefx = __commonJS((exports) => {
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const _compile = function(gl2, source, type) {
|
const _compile = function(source, type) {
|
||||||
const shader = gl2.createShader(type);
|
const shader = gl.createShader(type);
|
||||||
gl2.shaderSource(shader, source);
|
gl.shaderSource(shader, source);
|
||||||
gl2.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
if (!gl2.getShaderParameter(shader, gl2.COMPILE_STATUS)) {
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
throw new Error("Filter: GL compile failed", gl2.getShaderInfoLog(shader));
|
throw new Error("Filter: GL compile failed", gl.getShaderInfoLog(shader));
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
};
|
};
|
||||||
this.uniform = {};
|
this.uniform = {};
|
||||||
this.attribute = {};
|
this.attribute = {};
|
||||||
const _vsh = _compile(gl, vertexSource, gl.VERTEX_SHADER);
|
const _vsh = _compile(vertexSource, gl.VERTEX_SHADER);
|
||||||
const _fsh = _compile(gl, fragmentSource, gl.FRAGMENT_SHADER);
|
const _fsh = _compile(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
this.id = gl.createProgram();
|
this.id = gl.createProgram();
|
||||||
gl.attachShader(this.id, _vsh);
|
gl.attachShader(this.id, _vsh);
|
||||||
gl.attachShader(this.id, _fsh);
|
gl.attachShader(this.id, _fsh);
|
||||||
|
@ -5088,7 +5088,6 @@ var require_imagefx = __commonJS((exports) => {
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
if (_filterChain.length === 0) {
|
if (_filterChain.length === 0) {
|
||||||
const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
|
||||||
_draw();
|
_draw();
|
||||||
return _canvas;
|
return _canvas;
|
||||||
}
|
}
|
||||||
|
@ -5103,8 +5102,10 @@ var require_imagefx = __commonJS((exports) => {
|
||||||
if (width === _width && height === _height) {
|
if (width === _width && height === _height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_canvas.width = _width = width;
|
_canvas.width = width;
|
||||||
_canvas.height = _height = height;
|
_width = width;
|
||||||
|
_canvas.height = height;
|
||||||
|
_height = height;
|
||||||
if (!_vertexBuffer) {
|
if (!_vertexBuffer) {
|
||||||
const vertices = new Float32Array([
|
const vertices = new Float32Array([
|
||||||
-1,
|
-1,
|
||||||
|
@ -6041,8 +6042,10 @@ class Human {
|
||||||
else if (this.config.filter.width > 0)
|
else if (this.config.filter.width > 0)
|
||||||
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
||||||
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
offscreenCanvas.width = targetWidth;
|
if (offscreenCanvas.width !== targetWidth)
|
||||||
offscreenCanvas.height = targetHeight;
|
offscreenCanvas.width = targetWidth;
|
||||||
|
if (offscreenCanvas.height !== targetHeight)
|
||||||
|
offscreenCanvas.height = targetHeight;
|
||||||
const ctx = offscreenCanvas.getContext("2d");
|
const ctx = offscreenCanvas.getContext("2d");
|
||||||
if (input instanceof ImageData)
|
if (input instanceof ImageData)
|
||||||
ctx.putImageData(input, 0, 0);
|
ctx.putImageData(input, 0, 0);
|
||||||
|
@ -6084,9 +6087,9 @@ class Human {
|
||||||
} else {
|
} else {
|
||||||
const canvas = filtered || input;
|
const canvas = filtered || input;
|
||||||
let pixels;
|
let pixels;
|
||||||
if (this.config.backend === "webgl" || canvas instanceof ImageData)
|
if (this.config.backend === "webgl" || canvas instanceof ImageData) {
|
||||||
pixels = tf.browser.fromPixels(canvas);
|
pixels = tf.browser.fromPixels(canvas);
|
||||||
else {
|
} else {
|
||||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -120,7 +120,7 @@
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytes": 13664,
|
"bytes": 13768,
|
||||||
"imports": [
|
"imports": [
|
||||||
{
|
{
|
||||||
"path": "src/facemesh/facemesh.js"
|
"path": "src/facemesh/facemesh.js"
|
||||||
|
@ -152,7 +152,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytes": 19452,
|
"bytes": 19396,
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/posenet/buildParts.js": {
|
"src/posenet/buildParts.js": {
|
||||||
|
@ -275,7 +275,7 @@
|
||||||
"dist/human.esm-nobundle.js.map": {
|
"dist/human.esm-nobundle.js.map": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
"inputs": {},
|
"inputs": {},
|
||||||
"bytes": 254473
|
"bytes": 254548
|
||||||
},
|
},
|
||||||
"dist/human.esm-nobundle.js": {
|
"dist/human.esm-nobundle.js": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
|
@ -365,7 +365,7 @@
|
||||||
"bytesInOutput": 2270
|
"bytesInOutput": 2270
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytesInOutput": 20195
|
"bytesInOutput": 20137
|
||||||
},
|
},
|
||||||
"config.js": {
|
"config.js": {
|
||||||
"bytesInOutput": 2273
|
"bytesInOutput": 2273
|
||||||
|
@ -374,13 +374,13 @@
|
||||||
"bytesInOutput": 3012
|
"bytesInOutput": 3012
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytesInOutput": 11796
|
"bytesInOutput": 11904
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytesInOutput": 0
|
"bytesInOutput": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bytes": 158097
|
"bytes": 158147
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72068,19 +72068,19 @@ var require_imagefx = __commonJS((exports) => {
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const _compile = function(gl2, source, type) {
|
const _compile = function(source, type) {
|
||||||
const shader = gl2.createShader(type);
|
const shader = gl.createShader(type);
|
||||||
gl2.shaderSource(shader, source);
|
gl.shaderSource(shader, source);
|
||||||
gl2.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
if (!gl2.getShaderParameter(shader, gl2.COMPILE_STATUS)) {
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
throw new Error("Filter: GL compile failed", gl2.getShaderInfoLog(shader));
|
throw new Error("Filter: GL compile failed", gl.getShaderInfoLog(shader));
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
};
|
};
|
||||||
this.uniform = {};
|
this.uniform = {};
|
||||||
this.attribute = {};
|
this.attribute = {};
|
||||||
const _vsh = _compile(gl, vertexSource, gl.VERTEX_SHADER);
|
const _vsh = _compile(vertexSource, gl.VERTEX_SHADER);
|
||||||
const _fsh = _compile(gl, fragmentSource, gl.FRAGMENT_SHADER);
|
const _fsh = _compile(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
this.id = gl.createProgram();
|
this.id = gl.createProgram();
|
||||||
gl.attachShader(this.id, _vsh);
|
gl.attachShader(this.id, _vsh);
|
||||||
gl.attachShader(this.id, _fsh);
|
gl.attachShader(this.id, _fsh);
|
||||||
|
@ -72137,7 +72137,6 @@ var require_imagefx = __commonJS((exports) => {
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
if (_filterChain.length === 0) {
|
if (_filterChain.length === 0) {
|
||||||
const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
|
||||||
_draw();
|
_draw();
|
||||||
return _canvas;
|
return _canvas;
|
||||||
}
|
}
|
||||||
|
@ -72152,8 +72151,10 @@ var require_imagefx = __commonJS((exports) => {
|
||||||
if (width === _width && height === _height) {
|
if (width === _width && height === _height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_canvas.width = _width = width;
|
_canvas.width = width;
|
||||||
_canvas.height = _height = height;
|
_width = width;
|
||||||
|
_canvas.height = height;
|
||||||
|
_height = height;
|
||||||
if (!_vertexBuffer) {
|
if (!_vertexBuffer) {
|
||||||
const vertices = new Float32Array([
|
const vertices = new Float32Array([
|
||||||
-1,
|
-1,
|
||||||
|
@ -73090,8 +73091,10 @@ class Human {
|
||||||
else if (this.config.filter.width > 0)
|
else if (this.config.filter.width > 0)
|
||||||
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
||||||
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
offscreenCanvas.width = targetWidth;
|
if (offscreenCanvas.width !== targetWidth)
|
||||||
offscreenCanvas.height = targetHeight;
|
offscreenCanvas.width = targetWidth;
|
||||||
|
if (offscreenCanvas.height !== targetHeight)
|
||||||
|
offscreenCanvas.height = targetHeight;
|
||||||
const ctx = offscreenCanvas.getContext("2d");
|
const ctx = offscreenCanvas.getContext("2d");
|
||||||
if (input instanceof ImageData)
|
if (input instanceof ImageData)
|
||||||
ctx.putImageData(input, 0, 0);
|
ctx.putImageData(input, 0, 0);
|
||||||
|
@ -73133,9 +73136,9 @@ class Human {
|
||||||
} else {
|
} else {
|
||||||
const canvas = filtered || input;
|
const canvas = filtered || input;
|
||||||
let pixels;
|
let pixels;
|
||||||
if (this.config.backend === "webgl" || canvas instanceof ImageData)
|
if (this.config.backend === "webgl" || canvas instanceof ImageData) {
|
||||||
pixels = tf.browser.fromPixels(canvas);
|
pixels = tf.browser.fromPixels(canvas);
|
||||||
else {
|
} else {
|
||||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -294,7 +294,7 @@
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytes": 13664,
|
"bytes": 13768,
|
||||||
"imports": [
|
"imports": [
|
||||||
{
|
{
|
||||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.node.js"
|
"path": "node_modules/@tensorflow/tfjs/dist/tf.node.js"
|
||||||
|
@ -329,7 +329,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytes": 19452,
|
"bytes": 19396,
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/posenet/buildParts.js": {
|
"src/posenet/buildParts.js": {
|
||||||
|
@ -481,7 +481,7 @@
|
||||||
"dist/human.esm.js.map": {
|
"dist/human.esm.js.map": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
"inputs": {},
|
"inputs": {},
|
||||||
"bytes": 5127779
|
"bytes": 5127854
|
||||||
},
|
},
|
||||||
"dist/human.esm.js": {
|
"dist/human.esm.js": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
|
@ -628,7 +628,7 @@
|
||||||
"bytesInOutput": 2260
|
"bytesInOutput": 2260
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytesInOutput": 20195
|
"bytesInOutput": 20137
|
||||||
},
|
},
|
||||||
"config.js": {
|
"config.js": {
|
||||||
"bytesInOutput": 2273
|
"bytesInOutput": 2273
|
||||||
|
@ -637,13 +637,13 @@
|
||||||
"bytesInOutput": 3012
|
"bytesInOutput": 3012
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytesInOutput": 11786
|
"bytesInOutput": 11894
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytesInOutput": 0
|
"bytesInOutput": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bytes": 2927063
|
"bytes": 2927113
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72069,19 +72069,19 @@ var Human = (() => {
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const _compile = function(gl2, source, type) {
|
const _compile = function(source, type) {
|
||||||
const shader = gl2.createShader(type);
|
const shader = gl.createShader(type);
|
||||||
gl2.shaderSource(shader, source);
|
gl.shaderSource(shader, source);
|
||||||
gl2.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
if (!gl2.getShaderParameter(shader, gl2.COMPILE_STATUS)) {
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
throw new Error("Filter: GL compile failed", gl2.getShaderInfoLog(shader));
|
throw new Error("Filter: GL compile failed", gl.getShaderInfoLog(shader));
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
};
|
};
|
||||||
this.uniform = {};
|
this.uniform = {};
|
||||||
this.attribute = {};
|
this.attribute = {};
|
||||||
const _vsh = _compile(gl, vertexSource, gl.VERTEX_SHADER);
|
const _vsh = _compile(vertexSource, gl.VERTEX_SHADER);
|
||||||
const _fsh = _compile(gl, fragmentSource, gl.FRAGMENT_SHADER);
|
const _fsh = _compile(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
this.id = gl.createProgram();
|
this.id = gl.createProgram();
|
||||||
gl.attachShader(this.id, _vsh);
|
gl.attachShader(this.id, _vsh);
|
||||||
gl.attachShader(this.id, _fsh);
|
gl.attachShader(this.id, _fsh);
|
||||||
|
@ -72138,7 +72138,6 @@ var Human = (() => {
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
if (_filterChain.length === 0) {
|
if (_filterChain.length === 0) {
|
||||||
const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
|
||||||
_draw();
|
_draw();
|
||||||
return _canvas;
|
return _canvas;
|
||||||
}
|
}
|
||||||
|
@ -72153,8 +72152,10 @@ var Human = (() => {
|
||||||
if (width === _width && height === _height) {
|
if (width === _width && height === _height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_canvas.width = _width = width;
|
_canvas.width = width;
|
||||||
_canvas.height = _height = height;
|
_width = width;
|
||||||
|
_canvas.height = height;
|
||||||
|
_height = height;
|
||||||
if (!_vertexBuffer) {
|
if (!_vertexBuffer) {
|
||||||
const vertices = new Float32Array([
|
const vertices = new Float32Array([
|
||||||
-1,
|
-1,
|
||||||
|
@ -73095,8 +73096,10 @@ var Human = (() => {
|
||||||
else if (this.config.filter.width > 0)
|
else if (this.config.filter.width > 0)
|
||||||
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
||||||
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
offscreenCanvas.width = targetWidth;
|
if (offscreenCanvas.width !== targetWidth)
|
||||||
offscreenCanvas.height = targetHeight;
|
offscreenCanvas.width = targetWidth;
|
||||||
|
if (offscreenCanvas.height !== targetHeight)
|
||||||
|
offscreenCanvas.height = targetHeight;
|
||||||
const ctx = offscreenCanvas.getContext("2d");
|
const ctx = offscreenCanvas.getContext("2d");
|
||||||
if (input instanceof ImageData)
|
if (input instanceof ImageData)
|
||||||
ctx.putImageData(input, 0, 0);
|
ctx.putImageData(input, 0, 0);
|
||||||
|
@ -73138,9 +73141,9 @@ var Human = (() => {
|
||||||
} else {
|
} else {
|
||||||
const canvas = filtered || input;
|
const canvas = filtered || input;
|
||||||
let pixels;
|
let pixels;
|
||||||
if (this.config.backend === "webgl" || canvas instanceof ImageData)
|
if (this.config.backend === "webgl" || canvas instanceof ImageData) {
|
||||||
pixels = tf.browser.fromPixels(canvas);
|
pixels = tf.browser.fromPixels(canvas);
|
||||||
else {
|
} else {
|
||||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -294,7 +294,7 @@
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytes": 13664,
|
"bytes": 13768,
|
||||||
"imports": [
|
"imports": [
|
||||||
{
|
{
|
||||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.node.js"
|
"path": "node_modules/@tensorflow/tfjs/dist/tf.node.js"
|
||||||
|
@ -329,7 +329,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytes": 19452,
|
"bytes": 19396,
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/posenet/buildParts.js": {
|
"src/posenet/buildParts.js": {
|
||||||
|
@ -481,7 +481,7 @@
|
||||||
"dist/human.js.map": {
|
"dist/human.js.map": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
"inputs": {},
|
"inputs": {},
|
||||||
"bytes": 5131640
|
"bytes": 5131716
|
||||||
},
|
},
|
||||||
"dist/human.js": {
|
"dist/human.js": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
|
@ -628,7 +628,7 @@
|
||||||
"bytesInOutput": 2365
|
"bytesInOutput": 2365
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytesInOutput": 21613
|
"bytesInOutput": 21557
|
||||||
},
|
},
|
||||||
"config.js": {
|
"config.js": {
|
||||||
"bytesInOutput": 2471
|
"bytesInOutput": 2471
|
||||||
|
@ -637,10 +637,10 @@
|
||||||
"bytesInOutput": 3144
|
"bytesInOutput": 3144
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytesInOutput": 13119
|
"bytesInOutput": 13235
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bytes": 3073127
|
"bytes": 3073187
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5019,19 +5019,19 @@ var require_imagefx = __commonJS((exports2) => {
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const _compile = function(gl2, source, type) {
|
const _compile = function(source, type) {
|
||||||
const shader = gl2.createShader(type);
|
const shader = gl.createShader(type);
|
||||||
gl2.shaderSource(shader, source);
|
gl.shaderSource(shader, source);
|
||||||
gl2.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
if (!gl2.getShaderParameter(shader, gl2.COMPILE_STATUS)) {
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
throw new Error("Filter: GL compile failed", gl2.getShaderInfoLog(shader));
|
throw new Error("Filter: GL compile failed", gl.getShaderInfoLog(shader));
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
};
|
};
|
||||||
this.uniform = {};
|
this.uniform = {};
|
||||||
this.attribute = {};
|
this.attribute = {};
|
||||||
const _vsh = _compile(gl, vertexSource, gl.VERTEX_SHADER);
|
const _vsh = _compile(vertexSource, gl.VERTEX_SHADER);
|
||||||
const _fsh = _compile(gl, fragmentSource, gl.FRAGMENT_SHADER);
|
const _fsh = _compile(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
this.id = gl.createProgram();
|
this.id = gl.createProgram();
|
||||||
gl.attachShader(this.id, _vsh);
|
gl.attachShader(this.id, _vsh);
|
||||||
gl.attachShader(this.id, _fsh);
|
gl.attachShader(this.id, _fsh);
|
||||||
|
@ -5088,7 +5088,6 @@ var require_imagefx = __commonJS((exports2) => {
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
if (_filterChain.length === 0) {
|
if (_filterChain.length === 0) {
|
||||||
const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
|
||||||
_draw();
|
_draw();
|
||||||
return _canvas;
|
return _canvas;
|
||||||
}
|
}
|
||||||
|
@ -5103,8 +5102,10 @@ var require_imagefx = __commonJS((exports2) => {
|
||||||
if (width === _width && height === _height) {
|
if (width === _width && height === _height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_canvas.width = _width = width;
|
_canvas.width = width;
|
||||||
_canvas.height = _height = height;
|
_width = width;
|
||||||
|
_canvas.height = height;
|
||||||
|
_height = height;
|
||||||
if (!_vertexBuffer) {
|
if (!_vertexBuffer) {
|
||||||
const vertices = new Float32Array([
|
const vertices = new Float32Array([
|
||||||
-1,
|
-1,
|
||||||
|
@ -6044,8 +6045,10 @@ class Human {
|
||||||
else if (this.config.filter.width > 0)
|
else if (this.config.filter.width > 0)
|
||||||
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
||||||
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
offscreenCanvas.width = targetWidth;
|
if (offscreenCanvas.width !== targetWidth)
|
||||||
offscreenCanvas.height = targetHeight;
|
offscreenCanvas.width = targetWidth;
|
||||||
|
if (offscreenCanvas.height !== targetHeight)
|
||||||
|
offscreenCanvas.height = targetHeight;
|
||||||
const ctx = offscreenCanvas.getContext("2d");
|
const ctx = offscreenCanvas.getContext("2d");
|
||||||
if (input instanceof ImageData)
|
if (input instanceof ImageData)
|
||||||
ctx.putImageData(input, 0, 0);
|
ctx.putImageData(input, 0, 0);
|
||||||
|
@ -6087,9 +6090,9 @@ class Human {
|
||||||
} else {
|
} else {
|
||||||
const canvas = filtered || input;
|
const canvas = filtered || input;
|
||||||
let pixels;
|
let pixels;
|
||||||
if (this.config.backend === "webgl" || canvas instanceof ImageData)
|
if (this.config.backend === "webgl" || canvas instanceof ImageData) {
|
||||||
pixels = tf.browser.fromPixels(canvas);
|
pixels = tf.browser.fromPixels(canvas);
|
||||||
else {
|
} else {
|
||||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -73110,19 +73110,19 @@ var require_imagefx = __commonJS((exports2) => {
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const _compile = function(gl2, source, type) {
|
const _compile = function(source, type) {
|
||||||
const shader = gl2.createShader(type);
|
const shader = gl.createShader(type);
|
||||||
gl2.shaderSource(shader, source);
|
gl.shaderSource(shader, source);
|
||||||
gl2.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
if (!gl2.getShaderParameter(shader, gl2.COMPILE_STATUS)) {
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||||
throw new Error("Filter: GL compile failed", gl2.getShaderInfoLog(shader));
|
throw new Error("Filter: GL compile failed", gl.getShaderInfoLog(shader));
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
};
|
};
|
||||||
this.uniform = {};
|
this.uniform = {};
|
||||||
this.attribute = {};
|
this.attribute = {};
|
||||||
const _vsh = _compile(gl, vertexSource, gl.VERTEX_SHADER);
|
const _vsh = _compile(vertexSource, gl.VERTEX_SHADER);
|
||||||
const _fsh = _compile(gl, fragmentSource, gl.FRAGMENT_SHADER);
|
const _fsh = _compile(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
this.id = gl.createProgram();
|
this.id = gl.createProgram();
|
||||||
gl.attachShader(this.id, _vsh);
|
gl.attachShader(this.id, _vsh);
|
||||||
gl.attachShader(this.id, _fsh);
|
gl.attachShader(this.id, _fsh);
|
||||||
|
@ -73179,7 +73179,6 @@ var require_imagefx = __commonJS((exports2) => {
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
if (_filterChain.length === 0) {
|
if (_filterChain.length === 0) {
|
||||||
const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
|
||||||
_draw();
|
_draw();
|
||||||
return _canvas;
|
return _canvas;
|
||||||
}
|
}
|
||||||
|
@ -73194,8 +73193,10 @@ var require_imagefx = __commonJS((exports2) => {
|
||||||
if (width === _width && height === _height) {
|
if (width === _width && height === _height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_canvas.width = _width = width;
|
_canvas.width = width;
|
||||||
_canvas.height = _height = height;
|
_width = width;
|
||||||
|
_canvas.height = height;
|
||||||
|
_height = height;
|
||||||
if (!_vertexBuffer) {
|
if (!_vertexBuffer) {
|
||||||
const vertices = new Float32Array([
|
const vertices = new Float32Array([
|
||||||
-1,
|
-1,
|
||||||
|
@ -74135,8 +74136,10 @@ class Human {
|
||||||
else if (this.config.filter.width > 0)
|
else if (this.config.filter.width > 0)
|
||||||
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
||||||
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const offscreenCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
offscreenCanvas.width = targetWidth;
|
if (offscreenCanvas.width !== targetWidth)
|
||||||
offscreenCanvas.height = targetHeight;
|
offscreenCanvas.width = targetWidth;
|
||||||
|
if (offscreenCanvas.height !== targetHeight)
|
||||||
|
offscreenCanvas.height = targetHeight;
|
||||||
const ctx = offscreenCanvas.getContext("2d");
|
const ctx = offscreenCanvas.getContext("2d");
|
||||||
if (input instanceof ImageData)
|
if (input instanceof ImageData)
|
||||||
ctx.putImageData(input, 0, 0);
|
ctx.putImageData(input, 0, 0);
|
||||||
|
@ -74178,9 +74181,9 @@ class Human {
|
||||||
} else {
|
} else {
|
||||||
const canvas = filtered || input;
|
const canvas = filtered || input;
|
||||||
let pixels;
|
let pixels;
|
||||||
if (this.config.backend === "webgl" || canvas instanceof ImageData)
|
if (this.config.backend === "webgl" || canvas instanceof ImageData) {
|
||||||
pixels = tf.browser.fromPixels(canvas);
|
pixels = tf.browser.fromPixels(canvas);
|
||||||
else {
|
} else {
|
||||||
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
const tempCanvas = typeof OffscreenCanvas !== "undefined" ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement("canvas");
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -120,7 +120,7 @@
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytes": 13664,
|
"bytes": 13768,
|
||||||
"imports": [
|
"imports": [
|
||||||
{
|
{
|
||||||
"path": "src/facemesh/facemesh.js"
|
"path": "src/facemesh/facemesh.js"
|
||||||
|
@ -152,7 +152,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytes": 19452,
|
"bytes": 19396,
|
||||||
"imports": []
|
"imports": []
|
||||||
},
|
},
|
||||||
"src/posenet/buildParts.js": {
|
"src/posenet/buildParts.js": {
|
||||||
|
@ -275,7 +275,7 @@
|
||||||
"dist/human.node-nobundle.js.map": {
|
"dist/human.node-nobundle.js.map": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
"inputs": {},
|
"inputs": {},
|
||||||
"bytes": 268521
|
"bytes": 268701
|
||||||
},
|
},
|
||||||
"dist/human.node-nobundle.js": {
|
"dist/human.node-nobundle.js": {
|
||||||
"imports": [],
|
"imports": [],
|
||||||
|
@ -365,7 +365,7 @@
|
||||||
"bytesInOutput": 2273
|
"bytesInOutput": 2273
|
||||||
},
|
},
|
||||||
"src/imagefx.js": {
|
"src/imagefx.js": {
|
||||||
"bytesInOutput": 20197
|
"bytesInOutput": 20139
|
||||||
},
|
},
|
||||||
"config.js": {
|
"config.js": {
|
||||||
"bytesInOutput": 2275
|
"bytesInOutput": 2275
|
||||||
|
@ -377,10 +377,10 @@
|
||||||
"bytesInOutput": 47
|
"bytesInOutput": 47
|
||||||
},
|
},
|
||||||
"src/human.js": {
|
"src/human.js": {
|
||||||
"bytesInOutput": 11796
|
"bytesInOutput": 11904
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bytes": 158254
|
"bytes": 158304
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/human.js
13
src/human.js
|
@ -172,8 +172,8 @@ class Human {
|
||||||
if (this.config.filter.height > 0) targetHeight = this.config.filter.height;
|
if (this.config.filter.height > 0) targetHeight = this.config.filter.height;
|
||||||
else if (this.config.filter.width > 0) targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
else if (this.config.filter.width > 0) targetHeight = originalHeight * (this.config.filter.width / originalWidth);
|
||||||
const offscreenCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
|
const offscreenCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
|
||||||
offscreenCanvas.width = targetWidth;
|
if (offscreenCanvas.width !== targetWidth) offscreenCanvas.width = targetWidth;
|
||||||
offscreenCanvas.height = targetHeight;
|
if (offscreenCanvas.height !== targetHeight) offscreenCanvas.height = targetHeight;
|
||||||
const ctx = offscreenCanvas.getContext('2d');
|
const ctx = offscreenCanvas.getContext('2d');
|
||||||
if (input instanceof ImageData) ctx.putImageData(input, 0, 0);
|
if (input instanceof ImageData) ctx.putImageData(input, 0, 0);
|
||||||
else ctx.drawImage(input, 0, 0, originalWidth, originalHeight, 0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
else ctx.drawImage(input, 0, 0, originalWidth, originalHeight, 0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
||||||
|
@ -200,10 +200,11 @@ class Human {
|
||||||
} else {
|
} else {
|
||||||
const canvas = filtered || input;
|
const canvas = filtered || input;
|
||||||
let pixels;
|
let pixels;
|
||||||
// tf kernel-optimized method to get imagedata, also if input is imagedata, just use it
|
if ((this.config.backend === 'webgl') || (canvas instanceof ImageData)) {
|
||||||
if ((this.config.backend === 'webgl') || (canvas instanceof ImageData)) pixels = tf.browser.fromPixels(canvas);
|
// tf kernel-optimized method to get imagedata, also if input is imagedata, just use it
|
||||||
// cpu and wasm kernel does not implement efficient fromPixels method nor we can use canvas as-is, so we do a silly one more canvas
|
pixels = tf.browser.fromPixels(canvas);
|
||||||
else {
|
} else {
|
||||||
|
// cpu and wasm kernel does not implement efficient fromPixels method nor we can use canvas as-is, so we do a silly one more canvas
|
||||||
const tempCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
|
const tempCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
/* eslint-disable no-shadow */
|
|
||||||
/* eslint-disable prefer-rest-params */
|
|
||||||
/* eslint-disable no-sequences */
|
|
||||||
/* eslint-disable no-unused-vars */
|
|
||||||
/* eslint-disable no-unused-expressions */
|
|
||||||
/* eslint-disable no-multi-assign */
|
|
||||||
/* eslint-disable no-use-before-define */
|
/* eslint-disable no-use-before-define */
|
||||||
/*
|
/*
|
||||||
WebGLImageFilter - MIT Licensed
|
WebGLImageFilter - MIT Licensed
|
||||||
2013, Dominic Szablewski - phoboslab.org
|
2013, Dominic Szablewski - phoboslab.org
|
||||||
|
<https://github.com/phoboslab/WebGLImageFilter>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const WebGLProgram = function (gl, vertexSource, fragmentSource) {
|
const WebGLProgram = function (gl, vertexSource, fragmentSource) {
|
||||||
|
@ -19,7 +14,7 @@ const WebGLProgram = function (gl, vertexSource, fragmentSource) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const _compile = function (gl, source, type) {
|
const _compile = function (source, type) {
|
||||||
const shader = gl.createShader(type);
|
const shader = gl.createShader(type);
|
||||||
gl.shaderSource(shader, source);
|
gl.shaderSource(shader, source);
|
||||||
gl.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
|
@ -33,8 +28,8 @@ const WebGLProgram = function (gl, vertexSource, fragmentSource) {
|
||||||
this.uniform = {};
|
this.uniform = {};
|
||||||
this.attribute = {};
|
this.attribute = {};
|
||||||
|
|
||||||
const _vsh = _compile(gl, vertexSource, gl.VERTEX_SHADER);
|
const _vsh = _compile(vertexSource, gl.VERTEX_SHADER);
|
||||||
const _fsh = _compile(gl, fragmentSource, gl.FRAGMENT_SHADER);
|
const _fsh = _compile(fragmentSource, gl.FRAGMENT_SHADER);
|
||||||
|
|
||||||
this.id = gl.createProgram();
|
this.id = gl.createProgram();
|
||||||
gl.attachShader(this.id, _vsh);
|
gl.attachShader(this.id, _vsh);
|
||||||
|
@ -82,6 +77,7 @@ const WebGLImageFilter = function (params) {
|
||||||
if (!gl) throw new Error('Filter: getContext() failed');
|
if (!gl) throw new Error('Filter: getContext() failed');
|
||||||
|
|
||||||
this.addFilter = function (name) {
|
this.addFilter = function (name) {
|
||||||
|
// eslint-disable-next-line prefer-rest-params
|
||||||
const args = Array.prototype.slice.call(arguments, 1);
|
const args = Array.prototype.slice.call(arguments, 1);
|
||||||
const filter = _filter[name];
|
const filter = _filter[name];
|
||||||
|
|
||||||
|
@ -107,7 +103,7 @@ const WebGLImageFilter = function (params) {
|
||||||
|
|
||||||
// No filters? Just draw
|
// No filters? Just draw
|
||||||
if (_filterChain.length === 0) {
|
if (_filterChain.length === 0) {
|
||||||
const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
// const program = _compileShader(SHADER.FRAGMENT_IDENTITY);
|
||||||
_draw();
|
_draw();
|
||||||
return _canvas;
|
return _canvas;
|
||||||
}
|
}
|
||||||
|
@ -125,8 +121,10 @@ const WebGLImageFilter = function (params) {
|
||||||
// Same width/height? Nothing to do here
|
// Same width/height? Nothing to do here
|
||||||
if (width === _width && height === _height) { return; }
|
if (width === _width && height === _height) { return; }
|
||||||
|
|
||||||
_canvas.width = _width = width;
|
_canvas.width = width;
|
||||||
_canvas.height = _height = height;
|
_width = width;
|
||||||
|
_canvas.height = height;
|
||||||
|
_height = height;
|
||||||
|
|
||||||
// Create the context if we don't have it yet
|
// Create the context if we don't have it yet
|
||||||
if (!_vertexBuffer) {
|
if (!_vertexBuffer) {
|
||||||
|
@ -135,8 +133,8 @@ const WebGLImageFilter = function (params) {
|
||||||
-1, -1, 0, 1, 1, -1, 1, 1, -1, 1, 0, 0,
|
-1, -1, 0, 1, 1, -1, 1, 1, -1, 1, 0, 0,
|
||||||
-1, 1, 0, 0, 1, -1, 1, 1, 1, 1, 1, 0,
|
-1, 1, 0, 0, 1, -1, 1, 1, 1, 1, 1, 0,
|
||||||
]);
|
]);
|
||||||
_vertexBuffer = gl.createBuffer(),
|
// eslint-disable-next-line no-unused-expressions
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, _vertexBuffer);
|
(_vertexBuffer = gl.createBuffer(), gl.bindBuffer(gl.ARRAY_BUFFER, _vertexBuffer));
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
||||||
|
|
||||||
// Note sure if this is a good idea; at least it makes texture loading
|
// Note sure if this is a good idea; at least it makes texture loading
|
||||||
|
|
Loading…
Reference in New Issue