UNPKG

konva

Version:

<p align="center"> <img src="https://konvajs.org/android-chrome-192x192.png" alt="Konva logo" height="180" /> </p>

145 lines (144 loc) 5.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Mask = void 0; const Factory_1 = require("../Factory"); const Node_1 = require("../Node"); const Validators_1 = require("../Validators"); function pixelAt(idata, x, y) { var idx = (y * idata.width + x) * 4; var d = []; d.push(idata.data[idx++], idata.data[idx++], idata.data[idx++], idata.data[idx++]); return d; } function rgbDistance(p1, p2) { return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2) + Math.pow(p1[2] - p2[2], 2)); } function rgbMean(pTab) { var m = [0, 0, 0]; for (var i = 0; i < pTab.length; i++) { m[0] += pTab[i][0]; m[1] += pTab[i][1]; m[2] += pTab[i][2]; } m[0] /= pTab.length; m[1] /= pTab.length; m[2] /= pTab.length; return m; } function backgroundMask(idata, threshold) { var rgbv_no = pixelAt(idata, 0, 0); var rgbv_ne = pixelAt(idata, idata.width - 1, 0); var rgbv_so = pixelAt(idata, 0, idata.height - 1); var rgbv_se = pixelAt(idata, idata.width - 1, idata.height - 1); var thres = threshold || 10; if (rgbDistance(rgbv_no, rgbv_ne) < thres && rgbDistance(rgbv_ne, rgbv_se) < thres && rgbDistance(rgbv_se, rgbv_so) < thres && rgbDistance(rgbv_so, rgbv_no) < thres) { var mean = rgbMean([rgbv_ne, rgbv_no, rgbv_se, rgbv_so]); var mask = []; for (var i = 0; i < idata.width * idata.height; i++) { var d = rgbDistance(mean, [ idata.data[i * 4], idata.data[i * 4 + 1], idata.data[i * 4 + 2], ]); mask[i] = d < thres ? 0 : 255; } return mask; } } function applyMask(idata, mask) { for (var i = 0; i < idata.width * idata.height; i++) { idata.data[4 * i + 3] = mask[i]; } } function erodeMask(mask, sw, sh) { var weights = [1, 1, 1, 1, 0, 1, 1, 1, 1]; var side = Math.round(Math.sqrt(weights.length)); var halfSide = Math.floor(side / 2); var maskResult = []; for (var y = 0; y < sh; y++) { for (var x = 0; x < sw; x++) { var so = y * sw + x; var a = 0; for (var cy = 0; cy < side; cy++) { for (var cx = 0; cx < side; cx++) { var scy = y + cy - halfSide; var scx = x + cx - halfSide; if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) { var srcOff = scy * sw + scx; var wt = weights[cy * side + cx]; a += mask[srcOff] * wt; } } } maskResult[so] = a === 255 * 8 ? 255 : 0; } } return maskResult; } function dilateMask(mask, sw, sh) { var weights = [1, 1, 1, 1, 1, 1, 1, 1, 1]; var side = Math.round(Math.sqrt(weights.length)); var halfSide = Math.floor(side / 2); var maskResult = []; for (var y = 0; y < sh; y++) { for (var x = 0; x < sw; x++) { var so = y * sw + x; var a = 0; for (var cy = 0; cy < side; cy++) { for (var cx = 0; cx < side; cx++) { var scy = y + cy - halfSide; var scx = x + cx - halfSide; if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) { var srcOff = scy * sw + scx; var wt = weights[cy * side + cx]; a += mask[srcOff] * wt; } } } maskResult[so] = a >= 255 * 4 ? 255 : 0; } } return maskResult; } function smoothEdgeMask(mask, sw, sh) { var weights = [1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9]; var side = Math.round(Math.sqrt(weights.length)); var halfSide = Math.floor(side / 2); var maskResult = []; for (var y = 0; y < sh; y++) { for (var x = 0; x < sw; x++) { var so = y * sw + x; var a = 0; for (var cy = 0; cy < side; cy++) { for (var cx = 0; cx < side; cx++) { var scy = y + cy - halfSide; var scx = x + cx - halfSide; if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) { var srcOff = scy * sw + scx; var wt = weights[cy * side + cx]; a += mask[srcOff] * wt; } } } maskResult[so] = a; } } return maskResult; } const Mask = function (imageData) { var threshold = this.threshold(), mask = backgroundMask(imageData, threshold); if (mask) { mask = erodeMask(mask, imageData.width, imageData.height); mask = dilateMask(mask, imageData.width, imageData.height); mask = smoothEdgeMask(mask, imageData.width, imageData.height); applyMask(imageData, mask); } return imageData; }; exports.Mask = Mask; Factory_1.Factory.addGetterSetter(Node_1.Node, 'threshold', 0, (0, Validators_1.getNumberValidator)(), Factory_1.Factory.afterSetFilter);