代码拉取完成,页面将自动刷新
"use strict";
var clamp = require("clamp");
module.exports = calcSDF;
var INF = 1e20;
function calcSDF(src, options) {
if (!options) options = {};
var cutoff = options.cutoff == null ? 0.25 : options.cutoff;
var radius = options.radius == null ? 8 : options.radius;
var channel = options.channel || 0;
var w, h, size, data, intData, stride, ctx, canvas, imgData, i, l;
// handle image container
if (ArrayBuffer.isView(src) || Array.isArray(src)) {
if (!options.width || !options.height)
throw Error("For raw data width and height should be provided by options");
(w = options.width), (h = options.height);
data = src;
if (!options.stride) stride = Math.floor(src.length / w / h);
else stride = options.stride;
} else {
if (window.HTMLCanvasElement && src instanceof window.HTMLCanvasElement) {
canvas = src;
ctx = canvas.getContext("2d");
(w = canvas.width), (h = canvas.height);
imgData = ctx.getImageData(0, 0, w, h);
data = imgData.data;
stride = 4;
} else if (
window.CanvasRenderingContext2D &&
src instanceof window.CanvasRenderingContext2D
) {
canvas = src.canvas;
ctx = src;
(w = canvas.width), (h = canvas.height);
imgData = ctx.getImageData(0, 0, w, h);
data = imgData.data;
stride = 4;
} else if (window.ImageData && src instanceof window.ImageData) {
imgData = src;
(w = src.width), (h = src.height);
data = imgData.data;
stride = 4;
}
}
size = Math.max(w, h);
//convert int data to floats
if (
(window.Uint8ClampedArray && data instanceof window.Uint8ClampedArray) ||
(window.Uint8Array && data instanceof window.Uint8Array)
) {
intData = data;
data = Array(w * h);
for (i = 0, l = intData.length; i < l; i++) {
data[i] = intData[i * stride + channel] / 255;
}
} else {
if (stride !== 1) throw Error("Raw data can have only 1 value per pixel");
}
// temporary arrays for the distance transform
var gridOuter = Array(w * h);
var gridInner = Array(w * h);
var f = Array(size);
var d = Array(size);
var z = Array(size + 1);
var v = Array(size);
for (i = 0, l = w * h; i < l; i++) {
var a = data[i];
gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2);
gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2);
}
edt(gridOuter, w, h, f, d, v, z);
edt(gridInner, w, h, f, d, v, z);
var dist = window.Float32Array ? new Float32Array(w * h) : new Array(w * h);
for (i = 0, l = w * h; i < l; i++) {
dist[i] = clamp(1 - ((gridOuter[i] - gridInner[i]) / radius + cutoff), 0, 1);
}
return dist;
}
// 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/dt/
function edt(data, width, height, f, d, v, z) {
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
f[y] = data[y * width + x];
}
edt1d(f, d, v, z, height);
for (y = 0; y < height; y++) {
data[y * width + x] = d[y];
}
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
f[x] = data[y * width + x];
}
edt1d(f, d, v, z, width);
for (x = 0; x < width; x++) {
data[y * width + x] = Math.sqrt(d[x]);
}
}
}
// 1D squared distance transform
function edt1d(f, d, v, z, n) {
v[0] = 0;
z[0] = -INF;
z[1] = +INF;
for (var q = 1, k = 0; q < n; q++) {
var s = (f[q] + q * q - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
while (s <= z[k]) {
k--;
s = (f[q] + q * q - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
}
k++;
v[k] = q;
z[k] = s;
z[k + 1] = +INF;
}
for (q = 0, k = 0; q < n; q++) {
while (z[k + 1] < q) k++;
d[q] = (q - v[k]) * (q - v[k]) + f[v[k]];
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。