|
|
import { throwError, isNodePattern } from "@jimp/utils"; |
|
|
import { mulTable, shgTable } from "./blur-tables"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default (() => ({ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
blur(r, cb) { |
|
|
if (typeof r !== "number") return throwError.call(this, "r must be a number", cb); |
|
|
if (r < 1) return throwError.call(this, "r must be greater than 0", cb); |
|
|
let rsum; |
|
|
let gsum; |
|
|
let bsum; |
|
|
let asum; |
|
|
let x; |
|
|
let y; |
|
|
let i; |
|
|
let p; |
|
|
let p1; |
|
|
let p2; |
|
|
let yp; |
|
|
let yi; |
|
|
let yw; |
|
|
let pa; |
|
|
const wm = this.bitmap.width - 1; |
|
|
const hm = this.bitmap.height - 1; |
|
|
|
|
|
const rad1 = r + 1; |
|
|
const mulSum = mulTable[r]; |
|
|
const shgSum = shgTable[r]; |
|
|
const red = []; |
|
|
const green = []; |
|
|
const blue = []; |
|
|
const alpha = []; |
|
|
const vmin = []; |
|
|
const vmax = []; |
|
|
let iterations = 2; |
|
|
while (iterations-- > 0) { |
|
|
yi = 0; |
|
|
yw = 0; |
|
|
for (y = 0; y < this.bitmap.height; y++) { |
|
|
rsum = this.bitmap.data[yw] * rad1; |
|
|
gsum = this.bitmap.data[yw + 1] * rad1; |
|
|
bsum = this.bitmap.data[yw + 2] * rad1; |
|
|
asum = this.bitmap.data[yw + 3] * rad1; |
|
|
for (i = 1; i <= r; i++) { |
|
|
p = yw + ((i > wm ? wm : i) << 2); |
|
|
rsum += this.bitmap.data[p++]; |
|
|
gsum += this.bitmap.data[p++]; |
|
|
bsum += this.bitmap.data[p++]; |
|
|
asum += this.bitmap.data[p]; |
|
|
} |
|
|
for (x = 0; x < this.bitmap.width; x++) { |
|
|
red[yi] = rsum; |
|
|
green[yi] = gsum; |
|
|
blue[yi] = bsum; |
|
|
alpha[yi] = asum; |
|
|
if (y === 0) { |
|
|
vmin[x] = ((p = x + rad1) < wm ? p : wm) << 2; |
|
|
vmax[x] = (p = x - r) > 0 ? p << 2 : 0; |
|
|
} |
|
|
p1 = yw + vmin[x]; |
|
|
p2 = yw + vmax[x]; |
|
|
rsum += this.bitmap.data[p1++] - this.bitmap.data[p2++]; |
|
|
gsum += this.bitmap.data[p1++] - this.bitmap.data[p2++]; |
|
|
bsum += this.bitmap.data[p1++] - this.bitmap.data[p2++]; |
|
|
asum += this.bitmap.data[p1] - this.bitmap.data[p2]; |
|
|
yi++; |
|
|
} |
|
|
yw += this.bitmap.width << 2; |
|
|
} |
|
|
for (x = 0; x < this.bitmap.width; x++) { |
|
|
yp = x; |
|
|
rsum = red[yp] * rad1; |
|
|
gsum = green[yp] * rad1; |
|
|
bsum = blue[yp] * rad1; |
|
|
asum = alpha[yp] * rad1; |
|
|
for (i = 1; i <= r; i++) { |
|
|
yp += i > hm ? 0 : this.bitmap.width; |
|
|
rsum += red[yp]; |
|
|
gsum += green[yp]; |
|
|
bsum += blue[yp]; |
|
|
asum += alpha[yp]; |
|
|
} |
|
|
yi = x << 2; |
|
|
for (y = 0; y < this.bitmap.height; y++) { |
|
|
pa = asum * mulSum >>> shgSum; |
|
|
this.bitmap.data[yi + 3] = pa; |
|
|
|
|
|
|
|
|
if (pa > 255) { |
|
|
this.bitmap.data[yi + 3] = 255; |
|
|
} |
|
|
if (pa > 0) { |
|
|
pa = 255 / pa; |
|
|
this.bitmap.data[yi] = (rsum * mulSum >>> shgSum) * pa; |
|
|
this.bitmap.data[yi + 1] = (gsum * mulSum >>> shgSum) * pa; |
|
|
this.bitmap.data[yi + 2] = (bsum * mulSum >>> shgSum) * pa; |
|
|
} else { |
|
|
this.bitmap.data[yi + 2] = 0; |
|
|
this.bitmap.data[yi + 1] = 0; |
|
|
this.bitmap.data[yi] = 0; |
|
|
} |
|
|
if (x === 0) { |
|
|
vmin[y] = ((p = y + rad1) < hm ? p : hm) * this.bitmap.width; |
|
|
vmax[y] = (p = y - r) > 0 ? p * this.bitmap.width : 0; |
|
|
} |
|
|
p1 = x + vmin[y]; |
|
|
p2 = x + vmax[y]; |
|
|
rsum += red[p1] - red[p2]; |
|
|
gsum += green[p1] - green[p2]; |
|
|
bsum += blue[p1] - blue[p2]; |
|
|
asum += alpha[p1] - alpha[p2]; |
|
|
yi += this.bitmap.width << 2; |
|
|
} |
|
|
} |
|
|
} |
|
|
if (isNodePattern(cb)) { |
|
|
cb.call(this, null, this); |
|
|
} |
|
|
return this; |
|
|
} |
|
|
})); |
|
|
|