-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into tick-with-base
- Loading branch information
Showing
30 changed files
with
12,890 additions
and
1,549 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
export function blur(values, r) { | ||
if (!((r = +r) >= 0)) throw new RangeError("invalid r"); | ||
let length = values.length; | ||
if (!((length = Math.floor(length)) >= 0)) throw new RangeError("invalid length"); | ||
if (!length || !r) return values; | ||
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); | ||
return values; | ||
} | ||
|
||
export const blur2 = Blur2(blurf); | ||
|
||
export const blurImage = Blur2(blurfImage); | ||
|
||
function Blur2(blur) { | ||
return function(data, rx, ry = rx) { | ||
if (!((rx = +rx) >= 0)) throw new RangeError("invalid rx"); | ||
if (!((ry = +ry) >= 0)) throw new RangeError("invalid ry"); | ||
let {data: values, width, height} = data; | ||
if (!((width = Math.floor(width)) >= 0)) throw new RangeError("invalid width"); | ||
if (!((height = Math.floor(height !== undefined ? height : values.length / width)) >= 0)) throw new RangeError("invalid height"); | ||
if (!width || !height || (!rx && !ry)) return data; | ||
const blurx = rx && blur(rx); | ||
const blury = ry && blur(ry); | ||
const temp = values.slice(); | ||
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 (blurx) { | ||
blurh(blurx, values, temp, width, height); | ||
blurh(blurx, temp, values, width, height); | ||
blurh(blurx, values, temp, width, height); | ||
} 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) { | ||
for (let y = 0, n = w * h; y < n;) { | ||
blur(T, S, y, y += w, 1); | ||
} | ||
} | ||
|
||
function blurv(blur, T, S, w, h) { | ||
for (let x = 0, n = w * h; x < w; ++x) { | ||
blur(T, S, x, x + n, w); | ||
} | ||
} | ||
|
||
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 | ||
// S[start] (inclusive) and S[stop] (exclusive). If the given radius is not an | ||
// integer, S[i - r - 1] and S[i + r + 1] are added to the sum, each weighted | ||
// according to r - ⌊radius⌋. | ||
function blurf(radius) { | ||
const radius0 = Math.floor(radius); | ||
if (radius0 === radius) return bluri(radius); | ||
const t = radius - radius0; | ||
const w = 2 * radius + 1; | ||
return (T, S, start, stop, step) => { // stop must be aligned! | ||
if (!((stop -= step) >= start)) return; // inclusive stop | ||
let sum = radius0 * S[start]; | ||
const s0 = step * radius0; | ||
const s1 = s0 + step; | ||
for (let i = start, j = start + s0; i < j; i += step) { | ||
sum += S[Math.min(stop, i)]; | ||
} | ||
for (let i = start, j = stop; i <= j; i += step) { | ||
sum += S[Math.min(stop, i + s0)]; | ||
T[i] = (sum + t * (S[Math.max(start, i - s1)] + S[Math.min(stop, i + s1)])) / w; | ||
sum -= S[Math.max(start, i - s0)]; | ||
} | ||
}; | ||
} | ||
|
||
// Like blurf, but optimized for integer radius. | ||
function bluri(radius) { | ||
const w = 2 * radius + 1; | ||
return (T, S, start, stop, step) => { // stop must be aligned! | ||
if (!((stop -= step) >= start)) return; // inclusive stop | ||
let sum = radius * S[start]; | ||
const s = step * radius; | ||
for (let i = start, j = start + s; i < j; i += step) { | ||
sum += S[Math.min(stop, i)]; | ||
} | ||
for (let i = start, j = stop; i <= j; i += step) { | ||
sum += S[Math.min(stop, i + s)]; | ||
T[i] = sum / w; | ||
sum -= S[Math.max(start, i - s)]; | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
import quantile from "./quantile.js"; | ||
import quantile, {quantileIndex} from "./quantile.js"; | ||
|
||
export default function median(values, valueof) { | ||
return quantile(values, 0.5, valueof); | ||
} | ||
|
||
export function medianIndex(values, valueof) { | ||
return quantileIndex(values, 0.5, valueof); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.