source: node_modules/d3-array/src/blur.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 4.0 KB
Line 
1export function blur(values, r) {
2 if (!((r = +r) >= 0)) throw new RangeError("invalid r");
3 let length = values.length;
4 if (!((length = Math.floor(length)) >= 0)) throw new RangeError("invalid length");
5 if (!length || !r) return values;
6 const blur = blurf(r);
7 const temp = values.slice();
8 blur(values, temp, 0, length, 1);
9 blur(temp, values, 0, length, 1);
10 blur(values, temp, 0, length, 1);
11 return values;
12}
13
14export const blur2 = Blur2(blurf);
15
16export const blurImage = Blur2(blurfImage);
17
18function Blur2(blur) {
19 return function(data, rx, ry = rx) {
20 if (!((rx = +rx) >= 0)) throw new RangeError("invalid rx");
21 if (!((ry = +ry) >= 0)) throw new RangeError("invalid ry");
22 let {data: values, width, height} = data;
23 if (!((width = Math.floor(width)) >= 0)) throw new RangeError("invalid width");
24 if (!((height = Math.floor(height !== undefined ? height : values.length / width)) >= 0)) throw new RangeError("invalid height");
25 if (!width || !height || (!rx && !ry)) return data;
26 const blurx = rx && blur(rx);
27 const blury = ry && blur(ry);
28 const temp = values.slice();
29 if (blurx && blury) {
30 blurh(blurx, temp, values, width, height);
31 blurh(blurx, values, temp, width, height);
32 blurh(blurx, temp, values, width, height);
33 blurv(blury, values, temp, width, height);
34 blurv(blury, temp, values, width, height);
35 blurv(blury, values, temp, width, height);
36 } else if (blurx) {
37 blurh(blurx, values, temp, width, height);
38 blurh(blurx, temp, values, width, height);
39 blurh(blurx, values, temp, width, height);
40 } else if (blury) {
41 blurv(blury, values, temp, width, height);
42 blurv(blury, temp, values, width, height);
43 blurv(blury, values, temp, width, height);
44 }
45 return data;
46 };
47}
48
49function blurh(blur, T, S, w, h) {
50 for (let y = 0, n = w * h; y < n;) {
51 blur(T, S, y, y += w, 1);
52 }
53}
54
55function blurv(blur, T, S, w, h) {
56 for (let x = 0, n = w * h; x < w; ++x) {
57 blur(T, S, x, x + n, w);
58 }
59}
60
61function blurfImage(radius) {
62 const blur = blurf(radius);
63 return (T, S, start, stop, step) => {
64 start <<= 2, stop <<= 2, step <<= 2;
65 blur(T, S, start + 0, stop + 0, step);
66 blur(T, S, start + 1, stop + 1, step);
67 blur(T, S, start + 2, stop + 2, step);
68 blur(T, S, start + 3, stop + 3, step);
69 };
70}
71
72// Given a target array T, a source array S, sets each value T[i] to the average
73// of {S[i - r], …, S[i], …, S[i + r]}, where r = ⌊radius⌋, start <= i < stop,
74// for each i, i + step, i + 2 * step, etc., and where S[j] is clamped between
75// S[start] (inclusive) and S[stop] (exclusive). If the given radius is not an
76// integer, S[i - r - 1] and S[i + r + 1] are added to the sum, each weighted
77// according to r - ⌊radius⌋.
78function blurf(radius) {
79 const radius0 = Math.floor(radius);
80 if (radius0 === radius) return bluri(radius);
81 const t = radius - radius0;
82 const w = 2 * radius + 1;
83 return (T, S, start, stop, step) => { // stop must be aligned!
84 if (!((stop -= step) >= start)) return; // inclusive stop
85 let sum = radius0 * S[start];
86 const s0 = step * radius0;
87 const s1 = s0 + step;
88 for (let i = start, j = start + s0; i < j; i += step) {
89 sum += S[Math.min(stop, i)];
90 }
91 for (let i = start, j = stop; i <= j; i += step) {
92 sum += S[Math.min(stop, i + s0)];
93 T[i] = (sum + t * (S[Math.max(start, i - s1)] + S[Math.min(stop, i + s1)])) / w;
94 sum -= S[Math.max(start, i - s0)];
95 }
96 };
97}
98
99// Like blurf, but optimized for integer radius.
100function bluri(radius) {
101 const w = 2 * radius + 1;
102 return (T, S, start, stop, step) => { // stop must be aligned!
103 if (!((stop -= step) >= start)) return; // inclusive stop
104 let sum = radius * S[start];
105 const s = step * radius;
106 for (let i = start, j = start + s; i < j; i += step) {
107 sum += S[Math.min(stop, i)];
108 }
109 for (let i = start, j = stop; i <= j; i += step) {
110 sum += S[Math.min(stop, i + s)];
111 T[i] = sum / w;
112 sum -= S[Math.max(start, i - s)];
113 }
114 };
115}
Note: See TracBrowser for help on using the repository browser.