@100mslive/hms-virtual-background 1.3.2 → 1.3.3-alpha

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.
@@ -5,7 +5,9 @@ export declare class HMSVirtualBackgroundPlugin implements HMSVideoPlugin {
5
5
  personMaskWidth: number;
6
6
  personMaskHeight: number;
7
7
  isVirtualBackground: boolean;
8
- backgroundImage: HTMLImageElement | undefined;
8
+ backgroundImage: HTMLImageElement | null;
9
+ backgroundVideo: HTMLVideoElement | null;
10
+ backgroundType: string;
9
11
  loadModelCalled: boolean;
10
12
  blurValue: any;
11
13
  tfLite: any;
@@ -20,12 +22,14 @@ export declare class HMSVirtualBackgroundPlugin implements HMSVideoPlugin {
20
22
  personMask: ImageData;
21
23
  personMaskCanvas: HTMLCanvasElement;
22
24
  personMaskCtx: any;
23
- constructor(background: string);
25
+ filters: any;
26
+ enableSharpening?: boolean | false;
27
+ constructor(background: string, enableSharpening?: boolean);
24
28
  init(): Promise<void>;
25
29
  isSupported(): boolean;
26
30
  getName(): string;
27
31
  getPluginType(): HMSVideoPluginType;
28
- setBackground(path?: string | HTMLImageElement): Promise<void>;
32
+ setBackground(path?: string | HTMLImageElement | HTMLVideoElement): Promise<void>;
29
33
  stop(): void;
30
34
  processVideoFrame(input: HTMLCanvasElement, output: HTMLCanvasElement, skipProcessing?: boolean): Promise<void> | void;
31
35
  private setImage;
@@ -33,9 +37,12 @@ export declare class HMSVirtualBackgroundPlugin implements HMSVideoPlugin {
33
37
  private resizeInputData;
34
38
  private infer;
35
39
  private postProcessing;
40
+ private sharpenFilter;
36
41
  private drawPersonMask;
37
42
  private drawSegmentedBackground;
38
43
  private runSegmentation;
44
+ private fitVideoToBackground;
39
45
  private fitImageToBackground;
40
46
  private addBlurToBackground;
47
+ private initSharpenFilter;
41
48
  }
@@ -921,8 +921,16 @@ var TAG$1 = 'VBProcessor';
921
921
  var pkg$1 = /*#__PURE__*/require("../package.json");
922
922
 
923
923
  var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
924
- function HMSVirtualBackgroundPlugin(background) {
924
+ function HMSVirtualBackgroundPlugin(background, enableSharpening) {
925
+ if (enableSharpening === void 0) {
926
+ enableSharpening = false;
927
+ }
928
+
929
+ this.backgroundType = "none";
925
930
  this.background = background;
931
+ this.enableSharpening = enableSharpening;
932
+ this.backgroundImage = null;
933
+ this.backgroundVideo = null;
926
934
  this.personMaskWidth = 256;
927
935
  this.personMaskHeight = 144;
928
936
  this.isVirtualBackground = false;
@@ -941,6 +949,7 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
941
949
  this.personMaskCanvas.width = this.personMaskWidth;
942
950
  this.personMaskCanvas.height = this.personMaskHeight;
943
951
  this.personMaskCtx = this.personMaskCanvas.getContext('2d');
952
+ this.filters = {};
944
953
  this.log(TAG$1, "Virtual Background plugin created");
945
954
  this.setBackground(this.background);
946
955
  }
@@ -974,6 +983,11 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
974
983
  return this.tfLitePromise;
975
984
 
976
985
  case 11:
986
+ if (this.enableSharpening) {
987
+ this.initSharpenFilter();
988
+ }
989
+
990
+ case 12:
977
991
  case "end":
978
992
  return _context.stop();
979
993
  }
@@ -1002,71 +1016,121 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1002
1016
  };
1003
1017
 
1004
1018
  _proto.setBackground = /*#__PURE__*/function () {
1005
- var _setBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(path) {
1019
+ var _setBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(path) {
1020
+ var _this = this;
1021
+
1006
1022
  var img;
1007
- return runtime_1.wrap(function _callee2$(_context2) {
1023
+ return runtime_1.wrap(function _callee3$(_context3) {
1008
1024
  while (1) {
1009
- switch (_context2.prev = _context2.next) {
1025
+ switch (_context3.prev = _context3.next) {
1010
1026
  case 0:
1011
1027
  if (!(path !== "")) {
1012
- _context2.next = 24;
1028
+ _context3.next = 43;
1013
1029
  break;
1014
1030
  }
1015
1031
 
1016
1032
  if (!(path === "none")) {
1017
- _context2.next = 7;
1033
+ _context3.next = 8;
1018
1034
  break;
1019
1035
  }
1020
1036
 
1021
1037
  this.log(TAG$1, 'setting background to :', path);
1022
1038
  this.background = "none";
1039
+ this.backgroundType = "none";
1023
1040
  this.isVirtualBackground = false;
1024
- _context2.next = 22;
1041
+ _context3.next = 41;
1025
1042
  break;
1026
1043
 
1027
- case 7:
1044
+ case 8:
1028
1045
  if (!(path === "blur")) {
1029
- _context2.next = 13;
1046
+ _context3.next = 15;
1030
1047
  break;
1031
1048
  }
1032
1049
 
1033
1050
  this.log(TAG$1, 'setting background to :', path);
1034
1051
  this.background = "blur";
1052
+ this.backgroundType = "blur"; //TODO: check this
1053
+
1035
1054
  this.isVirtualBackground = false;
1036
- _context2.next = 22;
1055
+ _context3.next = 41;
1037
1056
  break;
1038
1057
 
1039
- case 13:
1040
- _context2.next = 15;
1058
+ case 15:
1059
+ if (!(path instanceof HTMLImageElement)) {
1060
+ _context3.next = 29;
1061
+ break;
1062
+ }
1063
+
1064
+ this.log("setting background to image", path);
1065
+ _context3.next = 19;
1041
1066
  return this.setImage(path);
1042
1067
 
1043
- case 15:
1044
- img = _context2.sent;
1068
+ case 19:
1069
+ img = _context3.sent;
1045
1070
 
1046
1071
  if (!(!img || !img.complete || !img.naturalHeight)) {
1047
- _context2.next = 20;
1072
+ _context3.next = 24;
1048
1073
  break;
1049
1074
  }
1050
1075
 
1051
1076
  throw new Error('Invalid image. Provide a valid and successfully loaded HTMLImageElement');
1052
1077
 
1053
- case 20:
1078
+ case 24:
1054
1079
  this.isVirtualBackground = true;
1055
1080
  this.backgroundImage = img;
1081
+ this.backgroundType = "image";
1056
1082
 
1057
- case 22:
1058
- _context2.next = 25;
1083
+ case 27:
1084
+ _context3.next = 41;
1059
1085
  break;
1060
1086
 
1061
- case 24:
1062
- this.log(TAG$1, "Not updating anything using the previous background Settings");
1087
+ case 29:
1088
+ if (!(path instanceof HTMLVideoElement)) {
1089
+ _context3.next = 40;
1090
+ break;
1091
+ }
1092
+
1093
+ this.log("setting background to video", path);
1094
+ this.isVirtualBackground = true;
1095
+ this.backgroundType = "video";
1096
+ this.backgroundVideo = path;
1097
+ this.backgroundVideo.crossOrigin = 'anonymous';
1098
+ this.backgroundVideo.muted = true;
1099
+ this.backgroundVideo.loop = true;
1100
+ this.backgroundVideo.oncanplaythrough = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2() {
1101
+ return runtime_1.wrap(function _callee2$(_context2) {
1102
+ while (1) {
1103
+ switch (_context2.prev = _context2.next) {
1104
+ case 0:
1105
+ _context2.next = 2;
1106
+ return _this.backgroundVideo.play();
1107
+
1108
+ case 2:
1109
+ case "end":
1110
+ return _context2.stop();
1111
+ }
1112
+ }
1113
+ }, _callee2);
1114
+ }));
1115
+ _context3.next = 41;
1116
+ break;
1063
1117
 
1064
- case 25:
1118
+ case 40:
1119
+ throw new Error("Invalid background supplied, see the docs to check supported background type");
1120
+
1121
+ case 41:
1122
+ _context3.next = 44;
1123
+ break;
1124
+
1125
+ case 43:
1126
+ throw new Error("Invalid background supplied, see the docs to check supported background type");
1127
+
1128
+ case 44:
1065
1129
  case "end":
1066
- return _context2.stop();
1130
+ return _context3.stop();
1067
1131
  }
1068
1132
  }
1069
- }, _callee2, this);
1133
+ }, _callee3, this);
1070
1134
  }));
1071
1135
 
1072
1136
  function setBackground(_x) {
@@ -1078,9 +1142,15 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1078
1142
 
1079
1143
  _proto.stop = function stop() {
1080
1144
  if (this.isVirtualBackground) {
1081
- var _this$backgroundImage;
1145
+ var _this$backgroundImage, _this$backgroundVideo;
1082
1146
 
1083
1147
  (_this$backgroundImage = this.backgroundImage) == null ? void 0 : _this$backgroundImage.removeAttribute('src');
1148
+ (_this$backgroundVideo = this.backgroundVideo) == null ? void 0 : _this$backgroundVideo.removeAttribute('src');
1149
+
1150
+ if (this.backgroundType == "video") {
1151
+ this.backgroundVideo.loop = false;
1152
+ this.backgroundVideo = null;
1153
+ }
1084
1154
  }
1085
1155
 
1086
1156
  if (this.outputCtx) {
@@ -1090,18 +1160,32 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1090
1160
  };
1091
1161
 
1092
1162
  _proto.processVideoFrame = function processVideoFrame(input, output, skipProcessing) {
1093
- var _this = this;
1163
+ var _this2 = this;
1094
1164
 
1095
1165
  if (!input || !output) {
1096
1166
  throw new Error('Plugin invalid input/output');
1097
1167
  }
1098
1168
 
1099
1169
  this.input = input;
1100
- this.output = output;
1170
+ this.output = output; // if(!this.t1){
1171
+ // this.output.style.position = "fixed"
1172
+ // this.output.style.top = String(0)
1173
+ // document.body.append(this.output)
1174
+ // this.t1 = true
1175
+ // }
1176
+
1101
1177
  var ctx = output.getContext('2d');
1102
1178
 
1103
1179
  if (ctx.canvas.width !== input.width) {
1104
1180
  ctx.canvas.width = input.width;
1181
+
1182
+ if (this.backgroundType == "video") {
1183
+ this.backgroundVideo.width = input.width;
1184
+ this.backgroundVideo.height = input.height;
1185
+ } // this.backgroundVideo!.style.top = String(0)
1186
+ // this.backgroundVideo!.style.position = "fixed"
1187
+ // document.body.append(this.backgroundVideo!)
1188
+
1105
1189
  }
1106
1190
 
1107
1191
  if (ctx.canvas.height !== input.height) {
@@ -1116,24 +1200,24 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1116
1200
  }
1117
1201
 
1118
1202
  var process = /*#__PURE__*/function () {
1119
- var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3() {
1120
- return runtime_1.wrap(function _callee3$(_context3) {
1203
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4() {
1204
+ return runtime_1.wrap(function _callee4$(_context4) {
1121
1205
  while (1) {
1122
- switch (_context3.prev = _context3.next) {
1206
+ switch (_context4.prev = _context4.next) {
1123
1207
  case 0:
1124
- _context3.next = 2;
1125
- return _this.runSegmentation(skipProcessing);
1208
+ _context4.next = 2;
1209
+ return _this2.runSegmentation(skipProcessing);
1126
1210
 
1127
1211
  case 2:
1128
1212
  case "end":
1129
- return _context3.stop();
1213
+ return _context4.stop();
1130
1214
  }
1131
1215
  }
1132
- }, _callee3);
1216
+ }, _callee4);
1133
1217
  }));
1134
1218
 
1135
1219
  return function process() {
1136
- return _ref.apply(this, arguments);
1220
+ return _ref2.apply(this, arguments);
1137
1221
  };
1138
1222
  }();
1139
1223
 
@@ -1147,13 +1231,13 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1147
1231
  };
1148
1232
 
1149
1233
  _proto.setImage = /*#__PURE__*/function () {
1150
- var _setImage = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4(image) {
1151
- return runtime_1.wrap(function _callee4$(_context4) {
1234
+ var _setImage = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5(image) {
1235
+ return runtime_1.wrap(function _callee5$(_context5) {
1152
1236
  while (1) {
1153
- switch (_context4.prev = _context4.next) {
1237
+ switch (_context5.prev = _context5.next) {
1154
1238
  case 0:
1155
1239
  image.crossOrigin = 'anonymous';
1156
- return _context4.abrupt("return", new Promise(function (resolve, reject) {
1240
+ return _context5.abrupt("return", new Promise(function (resolve, reject) {
1157
1241
  image.onload = function () {
1158
1242
  return resolve(image);
1159
1243
  };
@@ -1163,10 +1247,10 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1163
1247
 
1164
1248
  case 2:
1165
1249
  case "end":
1166
- return _context4.stop();
1250
+ return _context5.stop();
1167
1251
  }
1168
1252
  }
1169
- }, _callee4);
1253
+ }, _callee5);
1170
1254
  }));
1171
1255
 
1172
1256
  function setImage(_x2) {
@@ -1188,7 +1272,8 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1188
1272
 
1189
1273
  _proto.resizeInputData = function resizeInputData() {
1190
1274
  this.personMaskCtx.drawImage(this.input, 0, 0, this.input.width, this.input.height, 0, 0, this.personMaskWidth, this.personMaskHeight);
1191
- var imageData = this.personMaskCtx.getImageData(0, 0, this.personMaskWidth, this.personMaskHeight);
1275
+ var imageData = this.personMaskCtx.getImageData(0, 0, this.personMaskWidth, this.personMaskHeight); //
1276
+
1192
1277
  var inputMemoryOffset = this.tfLite._getInputMemoryOffset() / 4;
1193
1278
 
1194
1279
  for (var i = 0; i < this.personMaskPixelCount; i++) {
@@ -1237,11 +1322,32 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1237
1322
  this.outputCtx.globalCompositeOperation = 'source-in';
1238
1323
  this.outputCtx.filter = 'none'; // //Draw the foreground
1239
1324
 
1240
- this.outputCtx.drawImage(this.input, 0, 0); // //Draw the background
1325
+ this.outputCtx.drawImage(this.input, 0, 0);
1326
+
1327
+ if (this.enableSharpening) {
1328
+ this.sharpenFilter();
1329
+ } // //Draw the background
1330
+
1241
1331
 
1242
1332
  this.drawSegmentedBackground();
1243
1333
  };
1244
1334
 
1335
+ _proto.sharpenFilter = function sharpenFilter() {
1336
+ // adding sharpening filter to each frame to improve edges and brightness
1337
+ // The basic idea is that you take the weighed sum of a rectangle of pixels from the source image and use that as the output value using convolution filter
1338
+ // It is applied intermediate output with black background and only mask data in frame
1339
+ // Filter currently used is 3 x 3 sharpening filter with values as shown:
1340
+ // [ 0, -1, 0,
1341
+ // -1, 5, -1,
1342
+ // 0, -1, 0 ]
1343
+ var outputImageData = this.outputCtx.getImageData(0, 0, this.output.width, this.output.height); // filters you may try
1344
+ // [-1, -1, -1, -1, 9, -1, -1, -1, -1]
1345
+ //[0, -1, 0, -1, 5, -1, 0, -1, 0]
1346
+
1347
+ var output = this.filters.convolute(outputImageData);
1348
+ this.outputCtx.putImageData(output, 0, 0);
1349
+ };
1350
+
1245
1351
  _proto.drawPersonMask = function drawPersonMask() {
1246
1352
  this.outputCtx.drawImage(this.personMaskCanvas, 0, 0, this.personMaskWidth, this.personMaskHeight, 0, 0, this.output.width, this.output.height);
1247
1353
  };
@@ -1252,26 +1358,30 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1252
1358
  this.outputCtx.imageSmoothingQuality = 'high';
1253
1359
 
1254
1360
  if (this.isVirtualBackground) {
1255
- this.fitImageToBackground();
1361
+ if (this.backgroundType === "video") {
1362
+ this.fitVideoToBackground();
1363
+ } else if (this.backgroundType === "image") {
1364
+ this.fitImageToBackground();
1365
+ }
1256
1366
  } else {
1257
1367
  this.addBlurToBackground();
1258
1368
  }
1259
1369
  };
1260
1370
 
1261
1371
  _proto.runSegmentation = /*#__PURE__*/function () {
1262
- var _runSegmentation = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5(skipProcessing) {
1263
- return runtime_1.wrap(function _callee5$(_context5) {
1372
+ var _runSegmentation = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee6(skipProcessing) {
1373
+ return runtime_1.wrap(function _callee6$(_context6) {
1264
1374
  while (1) {
1265
- switch (_context5.prev = _context5.next) {
1375
+ switch (_context6.prev = _context6.next) {
1266
1376
  case 0:
1267
1377
  if (!this.tfLite) {
1268
- _context5.next = 5;
1378
+ _context6.next = 5;
1269
1379
  break;
1270
1380
  }
1271
1381
 
1272
1382
  // const start = performance.now();
1273
1383
  this.resizeInputData();
1274
- _context5.next = 4;
1384
+ _context6.next = 4;
1275
1385
  return this.infer(skipProcessing);
1276
1386
 
1277
1387
  case 4:
@@ -1280,10 +1390,10 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1280
1390
 
1281
1391
  case 5:
1282
1392
  case "end":
1283
- return _context5.stop();
1393
+ return _context6.stop();
1284
1394
  }
1285
1395
  }
1286
- }, _callee5, this);
1396
+ }, _callee6, this);
1287
1397
  }));
1288
1398
 
1289
1399
  function runSegmentation(_x3) {
@@ -1293,6 +1403,23 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1293
1403
  return runSegmentation;
1294
1404
  }();
1295
1405
 
1406
+ _proto.fitVideoToBackground = function fitVideoToBackground() {
1407
+ // let input_width: any, input_height: any, x_off: any, y_off: any
1408
+ // if ((this.backgroundVideo!.width / this.backgroundVideo!.height) < this.imageAspectRatio) {
1409
+ // input_width = this.backgroundVideo!.width;
1410
+ // input_height = this.backgroundVideo!.width/ this.imageAspectRatio;
1411
+ // x_off = 0;
1412
+ // y_off = (this.backgroundVideo!.height - input_height) / 2;
1413
+ // }
1414
+ // else {
1415
+ // input_height = this.backgroundVideo!.height;
1416
+ // input_width = this.backgroundVideo!.height * this.imageAspectRatio;
1417
+ // y_off = 0;
1418
+ // x_off = (this.backgroundVideo!.width - input_width) / 2;
1419
+ // }
1420
+ this.outputCtx.drawImage(this.backgroundVideo, 0, 0, this.output.width, this.output.height);
1421
+ };
1422
+
1296
1423
  _proto.fitImageToBackground = function fitImageToBackground() {
1297
1424
  var input_width, input_height, x_offset, y_offset;
1298
1425
 
@@ -1312,11 +1439,11 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1312
1439
  };
1313
1440
 
1314
1441
  _proto.addBlurToBackground = /*#__PURE__*/function () {
1315
- var _addBlurToBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee6() {
1442
+ var _addBlurToBackground = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee7() {
1316
1443
  var blurValue;
1317
- return runtime_1.wrap(function _callee6$(_context6) {
1444
+ return runtime_1.wrap(function _callee7$(_context7) {
1318
1445
  while (1) {
1319
- switch (_context6.prev = _context6.next) {
1446
+ switch (_context7.prev = _context7.next) {
1320
1447
  case 0:
1321
1448
  blurValue = '15px';
1322
1449
  if (this.input.width <= 160) blurValue = '5px';else if (this.input.width <= 320) blurValue = '10px';else if (this.input.width <= 640) blurValue = '15px';else if (this.input.width <= 960) blurValue = '20px';else if (this.input.width <= 1280) blurValue = '25px';else if (this.input.width <= 1920) blurValue = '30px';
@@ -1325,10 +1452,10 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1325
1452
 
1326
1453
  case 4:
1327
1454
  case "end":
1328
- return _context6.stop();
1455
+ return _context7.stop();
1329
1456
  }
1330
1457
  }
1331
- }, _callee6, this);
1458
+ }, _callee7, this);
1332
1459
  }));
1333
1460
 
1334
1461
  function addBlurToBackground() {
@@ -1338,6 +1465,80 @@ var HMSVirtualBackgroundPlugin = /*#__PURE__*/function () {
1338
1465
  return addBlurToBackground;
1339
1466
  }();
1340
1467
 
1468
+ _proto.initSharpenFilter = function initSharpenFilter() {
1469
+ var _this3 = this;
1470
+
1471
+ this.filters.tmpCanvas = document.createElement('canvas');
1472
+ this.filters.tmpCtx = this.filters.tmpCanvas.getContext('2d');
1473
+
1474
+ this.filters.createImageData = function (w, h) {
1475
+ return _this3.filters.tmpCtx.createImageData(w, h);
1476
+ };
1477
+
1478
+ this.filters.convolute = function (pixels, weights, opaque) {
1479
+ if (weights === void 0) {
1480
+ weights = [0, -1, 0, -1, 5, -1, 0, -1, 0];
1481
+ }
1482
+
1483
+ var side = Math.round(Math.sqrt(weights.length));
1484
+ var halfSide = Math.floor(side / 2);
1485
+ var src = pixels.data;
1486
+ var sw = pixels.width;
1487
+ var sh = pixels.height; // pad output by the convolution matrix
1488
+
1489
+ var w = sw;
1490
+ var h = sh;
1491
+
1492
+ var output = _this3.filters.createImageData(w, h);
1493
+
1494
+ var dst = output.data; // go through the destination image pixels
1495
+
1496
+ var alphaFac = opaque ? 1 : 0;
1497
+
1498
+ for (var y = 0; y < h; y = y + 1) {
1499
+ for (var x = 0; x < w; x = x + 1) {
1500
+ var dstOff = (y * w + x) * 4;
1501
+
1502
+ if (src[dstOff + 3] == 0) {
1503
+ continue;
1504
+ } else if (x < w && y < h) {
1505
+ var sy = y;
1506
+ var sx = x; // calculate the weighed sum of the source image pixels that
1507
+ // fall under the convolution matrix
1508
+
1509
+ var r = 0,
1510
+ g = 0,
1511
+ b = 0,
1512
+ a = 0;
1513
+
1514
+ for (var cy = 0; cy < side; cy++) {
1515
+ for (var cx = 0; cx < side; cx++) {
1516
+ var scy = sy + cy - halfSide;
1517
+ var scx = sx + cx - halfSide;
1518
+
1519
+ if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
1520
+ var srcOff = (scy * sw + scx) * 4;
1521
+ var wt = weights[cy * side + cx];
1522
+ r += src[srcOff] * wt;
1523
+ g += src[srcOff + 1] * wt;
1524
+ b += src[srcOff + 2] * wt;
1525
+ a += src[srcOff + 3] * wt;
1526
+ }
1527
+ }
1528
+ }
1529
+
1530
+ dst[dstOff] = r;
1531
+ dst[dstOff + 1] = g;
1532
+ dst[dstOff + 2] = b;
1533
+ dst[dstOff + 3] = a + alphaFac * (255 - a);
1534
+ }
1535
+ }
1536
+ }
1537
+
1538
+ return output;
1539
+ };
1540
+ };
1541
+
1341
1542
  return HMSVirtualBackgroundPlugin;
1342
1543
  }();
1343
1544