161 lines
6.3 KiB
JavaScript
161 lines
6.3 KiB
JavaScript
|
/*
|
||
|
Superfast Blur - a fast Box Blur For Canvas
|
||
|
|
||
|
Version: 0.5
|
||
|
Author: Mario Klingemann
|
||
|
Contact: mario@quasimondo.com
|
||
|
Website: http://www.quasimondo.com/BoxBlurForCanvas
|
||
|
Twitter: @quasimondo
|
||
|
|
||
|
In case you find this class useful - especially in commercial projects -
|
||
|
I am not totally unhappy for a small donation to my PayPal account
|
||
|
mario@quasimondo.de
|
||
|
|
||
|
Or support me on flattr:
|
||
|
https://flattr.com/thing/140066/Superfast-Blur-a-pretty-fast-Box-Blur-Effect-for-CanvasJavascript
|
||
|
|
||
|
Copyright (c) 2011 Mario Klingemann
|
||
|
|
||
|
Permission is hereby granted, free of charge, to any person
|
||
|
obtaining a copy of this software and associated documentation
|
||
|
files (the "Software"), to deal in the Software without
|
||
|
restriction, including without limitation the rights to use,
|
||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
copies of the Software, and to permit persons to whom the
|
||
|
Software is furnished to do so, subject to the following
|
||
|
conditions:
|
||
|
|
||
|
The above copyright notice and this permission notice shall be
|
||
|
included in all copies or substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
// eslint-disable-next-line max-len
|
||
|
const mul_table = [1, 57, 41, 21, 203, 34, 97, 73, 227, 91, 149, 62, 105, 45, 39, 137, 241, 107, 3, 173, 39, 71, 65, 238, 219, 101, 187, 87, 81, 151, 141, 133, 249, 117, 221, 209, 197, 187, 177, 169, 5, 153, 73, 139, 133, 127, 243, 233, 223, 107, 103, 99, 191, 23, 177, 171, 165, 159, 77, 149, 9, 139, 135, 131, 253, 245, 119, 231, 224, 109, 211, 103, 25, 195, 189, 23, 45, 175, 171, 83, 81, 79, 155, 151, 147, 9, 141, 137, 67, 131, 129, 251, 123, 30, 235, 115, 113, 221, 217, 53, 13, 51, 50, 49, 193, 189, 185, 91, 179, 175, 43, 169, 83, 163, 5, 79, 155, 19, 75, 147, 145, 143, 35, 69, 17, 67, 33, 65, 255, 251, 247, 243, 239, 59, 29, 229, 113, 111, 219, 27, 213, 105, 207, 51, 201, 199, 49, 193, 191, 47, 93, 183, 181, 179, 11, 87, 43, 85, 167, 165, 163, 161, 159, 157, 155, 77, 19, 75, 37, 73, 145, 143, 141, 35, 138, 137, 135, 67, 33, 131, 129, 255, 63, 250, 247, 61, 121, 239, 237, 117, 29, 229, 227, 225, 111, 55, 109, 216, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 48, 190, 47, 93, 185, 183, 181, 179, 178, 176, 175, 173, 171, 85, 21, 167, 165, 41, 163, 161, 5, 79, 157, 78, 154, 153, 19, 75, 149, 74, 147, 73, 144, 143, 71, 141, 140, 139, 137, 17, 135, 134, 133, 66, 131, 65, 129, 1];
|
||
|
// eslint-disable-next-line max-len
|
||
|
const shg_table = [0, 9, 10, 10, 14, 12, 14, 14, 16, 15, 16, 15, 16, 15, 15, 17, 18, 17, 12, 18, 16, 17, 17, 19, 19, 18, 19, 18, 18, 19, 19, 19, 20, 19, 20, 20, 20, 20, 20, 20, 15, 20, 19, 20, 20, 20, 21, 21, 21, 20, 20, 20, 21, 18, 21, 21, 21, 21, 20, 21, 17, 21, 21, 21, 22, 22, 21, 22, 22, 21, 22, 21, 19, 22, 22, 19, 20, 22, 22, 21, 21, 21, 22, 22, 22, 18, 22, 22, 21, 22, 22, 23, 22, 20, 23, 22, 22, 23, 23, 21, 19, 21, 21, 21, 23, 23, 23, 22, 23, 23, 21, 23, 22, 23, 18, 22, 23, 20, 22, 23, 23, 23, 21, 22, 20, 22, 21, 22, 24, 24, 24, 24, 24, 22, 21, 24, 23, 23, 24, 21, 24, 23, 24, 22, 24, 24, 22, 24, 24, 22, 23, 24, 24, 24, 20, 23, 22, 23, 24, 24, 24, 24, 24, 24, 24, 23, 21, 23, 22, 23, 24, 24, 24, 22, 24, 24, 24, 23, 22, 24, 24, 25, 23, 25, 25, 23, 24, 25, 25, 24, 22, 25, 25, 25, 24, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 23, 25, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 22, 25, 25, 23, 25, 25, 20, 24, 25, 24, 25, 25, 22, 24, 25, 24, 25, 24, 25, 25, 24, 25, 25, 25, 25, 22, 25, 25, 25, 24, 25, 24, 25, 18];
|
||
|
|
||
|
export default function boxBlurCanvasRGB(context, top_x, top_y, width, height, radius, iterations) {
|
||
|
if (Number.isNaN(radius) || radius < 1) return;
|
||
|
|
||
|
radius |= 0;
|
||
|
|
||
|
if (Number.isNaN(iterations)) iterations = 1;
|
||
|
iterations |= 0;
|
||
|
if (iterations > 3) iterations = 3;
|
||
|
if (iterations < 1) iterations = 1;
|
||
|
|
||
|
const imageData = context.getImageData(top_x, top_y, width, height);
|
||
|
|
||
|
const pixels = imageData.data;
|
||
|
|
||
|
let rsum;
|
||
|
let gsum;
|
||
|
let bsum;
|
||
|
let x;
|
||
|
let y;
|
||
|
let i;
|
||
|
let p;
|
||
|
let p1;
|
||
|
let p2;
|
||
|
let yp;
|
||
|
let yi;
|
||
|
let yw;
|
||
|
let wm = width - 1;
|
||
|
let hm = height - 1;
|
||
|
let rad1 = radius + 1;
|
||
|
|
||
|
let r = [];
|
||
|
let g = [];
|
||
|
let b = [];
|
||
|
|
||
|
let mul_sum = mul_table[radius];
|
||
|
let shg_sum = shg_table[radius];
|
||
|
|
||
|
let vmin = [];
|
||
|
let vmax = [];
|
||
|
|
||
|
while (iterations-- > 0) {
|
||
|
yw = yi = 0;
|
||
|
|
||
|
for (y = 0; y < height; y++) {
|
||
|
rsum = pixels[yw] * rad1;
|
||
|
gsum = pixels[yw + 1] * rad1;
|
||
|
bsum = pixels[yw + 2] * rad1;
|
||
|
|
||
|
for (i = 1; i <= radius; i++) {
|
||
|
p = yw + (((i > wm ? wm : i)) << 2);
|
||
|
rsum += pixels[p++];
|
||
|
gsum += pixels[p++];
|
||
|
bsum += pixels[p++];
|
||
|
}
|
||
|
|
||
|
for (x = 0; x < width; x++) {
|
||
|
r[yi] = rsum;
|
||
|
g[yi] = gsum;
|
||
|
b[yi] = bsum;
|
||
|
|
||
|
if (y == 0) {
|
||
|
vmin[x] = ((p = x + rad1) < wm ? p : wm) << 2;
|
||
|
vmax[x] = ((p = x - radius) > 0 ? p << 2 : 0);
|
||
|
}
|
||
|
|
||
|
p1 = yw + vmin[x];
|
||
|
p2 = yw + vmax[x];
|
||
|
|
||
|
rsum += pixels[p1++] - pixels[p2++];
|
||
|
gsum += pixels[p1++] - pixels[p2++];
|
||
|
bsum += pixels[p1++] - pixels[p2++];
|
||
|
|
||
|
yi++;
|
||
|
}
|
||
|
yw += (width << 2);
|
||
|
}
|
||
|
|
||
|
for (x = 0; x < width; x++) {
|
||
|
yp = x;
|
||
|
rsum = r[yp] * rad1;
|
||
|
gsum = g[yp] * rad1;
|
||
|
bsum = b[yp] * rad1;
|
||
|
|
||
|
for (i = 1; i <= radius; i++) {
|
||
|
yp += (i > hm ? 0 : width);
|
||
|
rsum += r[yp];
|
||
|
gsum += g[yp];
|
||
|
bsum += b[yp];
|
||
|
}
|
||
|
|
||
|
yi = x << 2;
|
||
|
for (y = 0; y < height; y++) {
|
||
|
pixels[yi] = (rsum * mul_sum) >>> shg_sum;
|
||
|
pixels[yi + 1] = (gsum * mul_sum) >>> shg_sum;
|
||
|
pixels[yi + 2] = (bsum * mul_sum) >>> shg_sum;
|
||
|
|
||
|
if (x == 0) {
|
||
|
vmin[y] = ((p = y + rad1) < hm ? p : hm) * width;
|
||
|
vmax[y] = ((p = y - radius) > 0 ? p * width : 0);
|
||
|
}
|
||
|
|
||
|
p1 = x + vmin[y];
|
||
|
p2 = x + vmax[y];
|
||
|
|
||
|
rsum += r[p1] - r[p2];
|
||
|
gsum += g[p1] - g[p2];
|
||
|
bsum += b[p1] - b[p2];
|
||
|
|
||
|
yi += width << 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
context.putImageData(imageData, top_x, top_y);
|
||
|
}
|