From c889f65ac0fbb7cfc5dc35f08bccc607028da91d Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 1 Jul 2022 20:22:47 -0400 Subject: [PATCH] blurImage --- src/blur.js | 40 ++++++++++++++++++++++++++++++---------- src/index.js | 2 +- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/blur.js b/src/blur.js index 9879c1a..49bc795 100644 --- a/src/blur.js +++ b/src/blur.js @@ -1,10 +1,9 @@ export function blur1(values, r) { if (!((r = +r) >= 0)) throw new RangeError("invalid r"); - const length = Math.floor(values.length); - if (!(length >= 0)) throw new RangeError("invalid length"); + const length = values.length; if (!length || !r) return values; - const temp = values.slice(); const blur = blurf(r); + const temp = values.slice(); blur(values, temp, 0, length, 1); blur(temp, values, 0, length, 1); blur(values, temp, 0, length, 1); @@ -17,27 +16,37 @@ export function blur2(data, rx, ry = rx) { let {data: values, width, height} = data; if (!((width = Math.floor(width)) >= 0)) throw new RangeError("invalid width"); if (!((height = Math.floor(height)) >= 0)) throw new RangeError("invalid height"); - if (!width || !height || (!rx && !ry)) return data; + blur2d(values, width, height, rx && blurf(rx), ry && blurf(ry)); + return data; +} + +export function blurImage(data, rx, ry = rx) { + if (!((rx = +rx) >= 0)) throw new RangeError("invalid rx"); + if (!((ry = +ry) >= 0)) throw new RangeError("invalid ry"); + const {data: values, width, height} = data; + blur2d(values, width, height, rx && blurfImage(rx), ry && blurfImage(ry)); + return data; +} + +function blur2d(values, width, height, blurx, blury) { + if (!width || !height || (!blurx && !blury)) return; const temp = values.slice(); - const blurx = blurf(rx); - const blury = blurf(ry); - if (rx && ry) { + if (blurx && blury) { blurh(blurx, temp, values, width, height); blurh(blurx, values, temp, width, height); blurh(blurx, temp, values, width, height); blurv(blury, values, temp, width, height); blurv(blury, temp, values, width, height); blurv(blury, values, temp, width, height); - } else if (rx) { + } else if (blurx) { blurh(blurx, values, temp, width, height); blurh(blurx, temp, values, width, height); blurh(blurx, values, temp, width, height); - } else if (ry) { + } else if (blury) { blurv(blury, values, temp, width, height); blurv(blury, temp, values, width, height); blurv(blury, values, temp, width, height); } - return data; } function blurh(blur, T, S, w, h) { @@ -52,6 +61,17 @@ function blurv(blur, T, S, w, h) { } } +function blurfImage(radius) { + const blur = blurf(radius); + return (T, S, start, stop, step) => { + start <<= 2, stop <<= 2, step <<= 2; + blur(T, S, start + 0, stop + 0, step); + blur(T, S, start + 1, stop + 1, step); + blur(T, S, start + 2, stop + 2, step); + blur(T, S, start + 3, stop + 3, step); + }; +} + // Given a target array T, a source array S, sets each value T[i] to the average // of {S[i - r], …, S[i], …, S[i + r]}, where r = ⌊radius⌋, start <= i < stop, // for each i, i + step, i + 2 * step, etc., and where S[j] is clamped between diff --git a/src/index.js b/src/index.js index 11b1b5e..74a901e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ export {default as bisect, bisectRight, bisectLeft, bisectCenter} from "./bisect.js"; export {default as ascending} from "./ascending.js"; export {default as bisector} from "./bisector.js"; -export {blur1, blur2} from "./blur.js"; +export {blur1, blur2, blurImage} from "./blur.js"; export {default as count} from "./count.js"; export {default as cross} from "./cross.js"; export {default as cumsum} from "./cumsum.js";