V1_commit_RGC

This commit is contained in:
2026-02-11 13:57:54 +01:00
commit ef397eedac
4901 changed files with 292881 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
; EditorConfig file: https://EditorConfig.org
; Install the "EditorConfig" plugin into your editor to use
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

View File

@@ -0,0 +1,5 @@
node_modules
dist
docs/jsdoc
!*.js

View File

@@ -0,0 +1,69 @@
'use strict';
module.exports = {
extends: ['ash-nazg/sauron-node'],
parserOptions: {
sourceType: 'module'
},
env: {
node: true,
browser: true
},
overrides: [
{
files: '*.md',
processor: 'markdown/markdown'
},
{
files: '**/*.md/*.js',
globals: {
require: true,
StackBlur: true,
width: true,
height: true,
top_x: true,
top_y: true,
radius: true,
imageData: true,
sourceImage: true,
targetCanvas: true,
blurAlphaChannel: true
},
rules: {
'import/unambiguous': 0,
'import/no-commonjs': 0,
'node/no-missing-import': 0,
'import/no-unresolved': ['error', {
ignore: ['stackblur-canvas']
}],
'node/no-missing-require': ['error', {
allowModules: ['stackblur-canvas']
}],
'no-shadow': 0,
'no-unused-vars': ['error', {varsIgnorePattern: 'StackBlur'}]
}
}, {
files: 'rollup.config.js',
env: {
node: true
}
}, {
files: '.*.js',
extends: ['plugin:node/recommended-script'],
rules: {
'import/unambiguous': 0,
'import/no-commonjs': 0
}
}
],
rules: {
'jsdoc/require-returns': ['error', {exemptedBy: ['see']}],
// Handled by Babel
'node/no-unsupported-features/es-syntax': 0,
// Would be good, but as not supported in older Node and browsers,
// would need polyfill for `Number.isNaN`
'unicorn/prefer-number-properties': 0,
'unicorn/prefer-math-trunc': 0
}
};

View File

@@ -0,0 +1,112 @@
# StackBlur CHANGES
## 2.7.0
- fix: use unsigned right shift to fix blur radius larger than 180 #59 (@kayahr)
- chore: update build files (@kayahr)
## 2.6.0
- feat: ImageBitmap support (@Jason11Q)
## 2.5.0
- Enhancement: boolean arg to skip setting canvas styles (@LukeeeeBennett)
- Build: As per latest devDeps.
- Docs: Update API docs as per latest
**Dev-facing:**
- Linting: As per ash-nazg
- npm: Switch to server without reported vulnerabilities
- npm: Switch to pnpm lock
- npm: Update devDeps (and switch to new ash-nazg peerDeps)
## 2.4.0
- Enhancement (image): add useOffsetWidth option for scaled images
- Refactoring: Move `let` to closer/deeper scope
- Linting: As per latest ash-nazg (add or avoid need for disable comments)
- npm: Update devDeps.
## 2.3.0
- Build: Update build files per latest devDeps
- Linting (ESLint): Switch to ash-nazg/sauron-node
- Linting (ESLint): Lint MD, HTML, hidden files
- Linting (ESLint): Switch to 2 sp. indent, fix max-len
- Linting (ESLint): Prefer `document.querySelector` in demo
- Linting (ESLint): Add a recommended extension (js) to eslintrc
- Maintenance: Add `.editorconfig`
- Mainenance: Use `.json` extension on `.babelrc`
- npm: Remove `package-lock.json` in favor of `yarn.lock`
- npm: Avoid bundling `rollup.config.js`
- npm: Move from deprecated `opn-cli` to `open-cli`
- npm: Add valid `engines` (pointing to minimum Node version until may confirm)
- npm: Update devDeps (except jsdoc which seems to still have a problem
with ESM exports: <https://github.com/jsdoc/jsdoc/issues/1644>)
## 2.2.0
- Build fix: Target 100% coverage
- Refactoring (minor): `x + x` -> `2 * x`
- npm Add prepublishOnly script for yarn
- npm: Update devDeps (no impact on build)
## 2.1.0
- Enhancement: Throw descriptive `TypeError` rather than silently returning
upon `processCanvasRGB`/`processCanvasRGBA` methods not supplying proper
canvas (dependent methods will throw anyways, so shouldn't be a
breaking change)
- Enhancement: Update TypeScript definition (@Jose Peleteiro)
## 2.0.0
- Breaking change: Remove now deprecated Bower
- Fix: Duck type with image or canvas in place of `instanceof` check
(and a broken one)
- Enhancement: Add JSDoc comments
- Linting (ESLint): Add ESLint with "standard" base
- Linting (Markdown): Add `.remarkrc`
- Linting (package.json): Add recommended properties
- Linting (HTML): Add empty favicon to suppress console
- License: Change MIT license file name to reflect license type (MIT)
- Docs: Move changelog to own file: `CHANGES.md`
- Demo: Move demo to own directory (with static server to avoid Chrome
security problems reaching out of folder)
- Demo: Move JS and CSS to separate files for easier linting/examination
- Build: Move from Grunt to Rollup, supporting ES6 Modules distribution
as well as UMD
- Build: Add npm-recommended `package-lock.json`
- npm: Add start, eslint, rollup, open-docs, docs scripts
- npm: Add `module` for ES6 module discovery and switch `main` to point
to `dist`
## 1.4.1
- Moves `grunt-cli` to `devDependencies` (#23)
## 1.4.0
- Allows the lib to be used with node-canvas
## 1.3.0
- TypeScript typings added
## 1.2.1
- Includes built files in the NPM packgage
## 1.2.0
- Remove alerts and obsolete `netscape.security.PrivilegeManager`
## 1.1.0
- Allow blur to be applied to `ImageData` directly (thanks @WebSeed)
## 1.0.0
- First Release

View File

@@ -0,0 +1,22 @@
Copyright (c) 2010 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.

View File

@@ -0,0 +1,147 @@
# StackBlur.js
[![NPM Version](https://img.shields.io/npm/v/stackblur-canvas.svg)][pkg-npm]
[![License](https://img.shields.io/npm/l/stackblur-canvas.svg)](https://github.com/flozz/StackBlur/blob/master/COPYING)
StackBlur.js is a fast, almost Gaussian blur created by Mario Klingemann.
* **More informations:** <http://incubator.quasimondo.com/processing/fast_blur_deluxe.php>
* **Algorithm:** <https://medium.com/better-programming/blurring-image-algorithm-example-in-android-cec81911cd5e>
* **Demo:** <http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html>
Original source:
* <http://www.quasimondo.com/StackBlurForCanvas/StackBlur.js>
## Getting Started
### Standalone version
To use the standalone version,
download the [latest zip][dl-zip-master] from Github or clone the repository
```
git clone git@github.com:flozz/StackBlur.git
```
and include the `dist/stackblur.js` or `dist/stackblur.min.js` file in your HTML page:
```html
<script src="StackBlur/dist/stackblur.js"></script>
```
### Node
To use the [NPM package][pkg-npm],
install the package:
```
npm install --save stackblur-canvas
```
and require it where needed
```js
const StackBlur = require('stackblur-canvas');
```
### Browsers
If you are only supporting modern browsers, you may use ES6 Modules directly:
```js
import * as StackBlur from
'./node_modules/stackblur-canvas/dist/stackblur-es.min.js';
```
Or, if you are using Rollup in your own project, use the [node-resolve](https://github.com/rollup/rollup-plugin-node-resolve) plugin,
and import by just referencing the module:
```js
import * as StackBlur from 'stackblur-canvas';
```
## API
See also the docs in [docs/jsdoc](./docs/jsdoc/index.html).
**Image as source:**
```js
StackBlur.image(sourceImage, targetCanvas, radius, blurAlphaChannel);
```
* `sourceImage`: the `HTMLImageElement` or its `id`.
* `targetCanvas`: the `HTMLCanvasElement` or its `id`.
* `radius`: the radius of the blur.
* `blurAlphaChannel`: Set it to `true` if you want to blur a RGBA image (optional, default = `false`)
**RGBA Canvas as source:**
```js
StackBlur.canvasRGBA(targetCanvas, top_x, top_y, width, height, radius);
```
* `targetCanvas`: the `HTMLCanvasElement`.
* `top_x`: the horizontal coordinate of the top-left corner of the rectangle to blur.
* `top_y`: the vertical coordinate of the top-left corner of the rectangle to blur.
* `width`: the width of the rectangle to blur.
* `height`: the height of the rectangle to blur.
* `radius`: the radius of the blur.
**RGB Canvas as source:**
```js
StackBlur.canvasRGB(targetCanvas, top_x, top_y, width, height, radius);
```
* `targetCanvas`: the `HTMLCanvasElement`.
* `top_x`: the horizontal coordinate of the top-left corner of the rectangle to blur.
* `top_y`: the vertical coordinate of the top-left corner of the rectangle to blur.
* `width`: the width of the rectangle to blur.
* `height`: the height of the rectangle to blur.
* `radius`: the radius of the blur.
**RGBA ImageData as source:**
```js
StackBlur.imageDataRGBA(imageData, top_x, top_y, width, height, radius);
```
* `imageData`: the canvas' `ImageData`.
* `top_x`: the horizontal coordinate of the top-left corner of the rectangle to blur.
* `top_y`: the vertical coordinate of the top-left corner of the rectangle to blur.
* `width`: the width of the rectangle to blur.
* `height`: the height of the rectangle to blur.
* `radius`: the radius of the blur.
**RGB ImageData as source:**
```js
StackBlur.imageDataRGB(imageData, top_x, top_y, width, height, radius);
```
* `imageData`: the canvas' `ImageData`.
* `top_x`: the horizontal coordinate of the top-left corner of the rectangle to blur.
* `top_y`: the vertical coordinate of the top-left corner of the rectangle to blur.
* `width`: the width of the rectangle to blur.
* `height`: the height of the rectangle to blur.
* `radius`: the radius of the blur.
## Hacking
### Building
This library is built using [Rollup](https://rollupjs.org/guide/en).
If you change something in the `src/` folder, use the following command
to re-build the files in the `dist/` folder:
`npm run rollup`
[dl-zip-master]: https://github.com/flozz/StackBlur/archive/master.zip
[pkg-npm]: https://www.npmjs.com/package/stackblur-canvas
[grunt]: http://gruntjs.com/

View File

@@ -0,0 +1,639 @@
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
/* eslint-disable no-bitwise -- used for calculations */
/* eslint-disable unicorn/prefer-query-selector -- aiming at
backward-compatibility */
/**
* StackBlur - a fast almost Gaussian Blur For Canvas
*
* 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:
* {@link https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript}.
*
* @module StackBlur
* @author Mario Klingemann
* Contact: mario@quasimondo.com
* Website: {@link http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html}
* Twitter: @quasimondo
*
* @copyright (c) 2010 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.
*/
var mulTable = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259];
var shgTable = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24];
/**
* @param {string|HTMLImageElement} img
* @param {string|HTMLCanvasElement} canvas
* @param {Float} radius
* @param {boolean} blurAlphaChannel
* @param {boolean} useOffset
* @param {boolean} skipStyles
* @returns {undefined}
*/
function processImage(img, canvas, radius, blurAlphaChannel, useOffset, skipStyles) {
if (typeof img === 'string') {
img = document.getElementById(img);
}
if (!img || Object.prototype.toString.call(img).slice(8, -1) === 'HTMLImageElement' && !('naturalWidth' in img)) {
return;
}
var dimensionType = useOffset ? 'offset' : 'natural';
var w = img[dimensionType + 'Width'];
var h = img[dimensionType + 'Height']; // add ImageBitmap support,can blur texture source
if (Object.prototype.toString.call(img).slice(8, -1) === 'ImageBitmap') {
w = img.width;
h = img.height;
}
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!canvas || !('getContext' in canvas)) {
return;
}
if (!skipStyles) {
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
}
canvas.width = w;
canvas.height = h;
var context = canvas.getContext('2d');
context.clearRect(0, 0, w, h);
context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, w, h);
if (isNaN(radius) || radius < 1) {
return;
}
if (blurAlphaChannel) {
processCanvasRGBA(canvas, 0, 0, w, h, radius);
} else {
processCanvasRGB(canvas, 0, 0, w, h, radius);
}
}
/**
* @param {string|HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @throws {Error|TypeError}
* @returns {ImageData} See {@link https://html.spec.whatwg.org/multipage/canvas.html#imagedata}
*/
function getImageDataFromCanvas(canvas, topX, topY, width, height) {
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!canvas || _typeof(canvas) !== 'object' || !('getContext' in canvas)) {
throw new TypeError('Expecting canvas with `getContext` method ' + 'in processCanvasRGB(A) calls!');
}
var context = canvas.getContext('2d');
try {
return context.getImageData(topX, topY, width, height);
} catch (e) {
throw new Error('unable to access image data: ' + e);
}
}
/**
* @param {HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {undefined}
*/
function processCanvasRGBA(canvas, topX, topY, width, height, radius) {
if (isNaN(radius) || radius < 1) {
return;
}
radius |= 0;
var imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
imageData = processImageDataRGBA(imageData, topX, topY, width, height, radius);
canvas.getContext('2d').putImageData(imageData, topX, topY);
}
/**
* @param {ImageData} imageData
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {ImageData}
*/
function processImageDataRGBA(imageData, topX, topY, width, height, radius) {
var pixels = imageData.data;
var div = 2 * radius + 1; // const w4 = width << 2;
var widthMinus1 = width - 1;
var heightMinus1 = height - 1;
var radiusPlus1 = radius + 1;
var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
var stackStart = new BlurStack();
var stack = stackStart;
var stackEnd;
for (var i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i === radiusPlus1) {
stackEnd = stack;
}
}
stack.next = stackStart;
var stackIn = null,
stackOut = null,
yw = 0,
yi = 0;
var mulSum = mulTable[radius];
var shgSum = shgTable[radius];
for (var y = 0; y < height; y++) {
stack = stackStart;
var pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
pa = pixels[yi + 3];
for (var _i = 0; _i < radiusPlus1; _i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack.a = pa;
stack = stack.next;
}
var rInSum = 0,
gInSum = 0,
bInSum = 0,
aInSum = 0,
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
aOutSum = radiusPlus1 * pa,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb,
aSum = sumFactor * pa;
for (var _i2 = 1; _i2 < radiusPlus1; _i2++) {
var p = yi + ((widthMinus1 < _i2 ? widthMinus1 : _i2) << 2);
var r = pixels[p],
g = pixels[p + 1],
b = pixels[p + 2],
a = pixels[p + 3];
var rbs = radiusPlus1 - _i2;
rSum += (stack.r = r) * rbs;
gSum += (stack.g = g) * rbs;
bSum += (stack.b = b) * rbs;
aSum += (stack.a = a) * rbs;
rInSum += r;
gInSum += g;
bInSum += b;
aInSum += a;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (var x = 0; x < width; x++) {
var paInitial = aSum * mulSum >>> shgSum;
pixels[yi + 3] = paInitial;
if (paInitial !== 0) {
var _a2 = 255 / paInitial;
pixels[yi] = (rSum * mulSum >>> shgSum) * _a2;
pixels[yi + 1] = (gSum * mulSum >>> shgSum) * _a2;
pixels[yi + 2] = (bSum * mulSum >>> shgSum) * _a2;
} else {
pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
}
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
aSum -= aOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
aOutSum -= stackIn.a;
var _p = x + radius + 1;
_p = yw + (_p < widthMinus1 ? _p : widthMinus1) << 2;
rInSum += stackIn.r = pixels[_p];
gInSum += stackIn.g = pixels[_p + 1];
bInSum += stackIn.b = pixels[_p + 2];
aInSum += stackIn.a = pixels[_p + 3];
rSum += rInSum;
gSum += gInSum;
bSum += bInSum;
aSum += aInSum;
stackIn = stackIn.next;
var _stackOut = stackOut,
_r = _stackOut.r,
_g = _stackOut.g,
_b = _stackOut.b,
_a = _stackOut.a;
rOutSum += _r;
gOutSum += _g;
bOutSum += _b;
aOutSum += _a;
rInSum -= _r;
gInSum -= _g;
bInSum -= _b;
aInSum -= _a;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (var _x = 0; _x < width; _x++) {
yi = _x << 2;
var _pr = pixels[yi],
_pg = pixels[yi + 1],
_pb = pixels[yi + 2],
_pa = pixels[yi + 3],
_rOutSum = radiusPlus1 * _pr,
_gOutSum = radiusPlus1 * _pg,
_bOutSum = radiusPlus1 * _pb,
_aOutSum = radiusPlus1 * _pa,
_rSum = sumFactor * _pr,
_gSum = sumFactor * _pg,
_bSum = sumFactor * _pb,
_aSum = sumFactor * _pa;
stack = stackStart;
for (var _i3 = 0; _i3 < radiusPlus1; _i3++) {
stack.r = _pr;
stack.g = _pg;
stack.b = _pb;
stack.a = _pa;
stack = stack.next;
}
var yp = width;
var _gInSum = 0,
_bInSum = 0,
_aInSum = 0,
_rInSum = 0;
for (var _i4 = 1; _i4 <= radius; _i4++) {
yi = yp + _x << 2;
var _rbs = radiusPlus1 - _i4;
_rSum += (stack.r = _pr = pixels[yi]) * _rbs;
_gSum += (stack.g = _pg = pixels[yi + 1]) * _rbs;
_bSum += (stack.b = _pb = pixels[yi + 2]) * _rbs;
_aSum += (stack.a = _pa = pixels[yi + 3]) * _rbs;
_rInSum += _pr;
_gInSum += _pg;
_bInSum += _pb;
_aInSum += _pa;
stack = stack.next;
if (_i4 < heightMinus1) {
yp += width;
}
}
yi = _x;
stackIn = stackStart;
stackOut = stackEnd;
for (var _y = 0; _y < height; _y++) {
var _p2 = yi << 2;
pixels[_p2 + 3] = _pa = _aSum * mulSum >>> shgSum;
if (_pa > 0) {
_pa = 255 / _pa;
pixels[_p2] = (_rSum * mulSum >>> shgSum) * _pa;
pixels[_p2 + 1] = (_gSum * mulSum >>> shgSum) * _pa;
pixels[_p2 + 2] = (_bSum * mulSum >>> shgSum) * _pa;
} else {
pixels[_p2] = pixels[_p2 + 1] = pixels[_p2 + 2] = 0;
}
_rSum -= _rOutSum;
_gSum -= _gOutSum;
_bSum -= _bOutSum;
_aSum -= _aOutSum;
_rOutSum -= stackIn.r;
_gOutSum -= stackIn.g;
_bOutSum -= stackIn.b;
_aOutSum -= stackIn.a;
_p2 = _x + ((_p2 = _y + radiusPlus1) < heightMinus1 ? _p2 : heightMinus1) * width << 2;
_rSum += _rInSum += stackIn.r = pixels[_p2];
_gSum += _gInSum += stackIn.g = pixels[_p2 + 1];
_bSum += _bInSum += stackIn.b = pixels[_p2 + 2];
_aSum += _aInSum += stackIn.a = pixels[_p2 + 3];
stackIn = stackIn.next;
_rOutSum += _pr = stackOut.r;
_gOutSum += _pg = stackOut.g;
_bOutSum += _pb = stackOut.b;
_aOutSum += _pa = stackOut.a;
_rInSum -= _pr;
_gInSum -= _pg;
_bInSum -= _pb;
_aInSum -= _pa;
stackOut = stackOut.next;
yi += width;
}
}
return imageData;
}
/**
* @param {HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {undefined}
*/
function processCanvasRGB(canvas, topX, topY, width, height, radius) {
if (isNaN(radius) || radius < 1) {
return;
}
radius |= 0;
var imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
imageData = processImageDataRGB(imageData, topX, topY, width, height, radius);
canvas.getContext('2d').putImageData(imageData, topX, topY);
}
/**
* @param {ImageData} imageData
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {ImageData}
*/
function processImageDataRGB(imageData, topX, topY, width, height, radius) {
var pixels = imageData.data;
var div = 2 * radius + 1; // const w4 = width << 2;
var widthMinus1 = width - 1;
var heightMinus1 = height - 1;
var radiusPlus1 = radius + 1;
var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
var stackStart = new BlurStack();
var stack = stackStart;
var stackEnd;
for (var i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i === radiusPlus1) {
stackEnd = stack;
}
}
stack.next = stackStart;
var stackIn = null;
var stackOut = null;
var mulSum = mulTable[radius];
var shgSum = shgTable[radius];
var p, rbs;
var yw = 0,
yi = 0;
for (var y = 0; y < height; y++) {
var pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb;
stack = stackStart;
for (var _i5 = 0; _i5 < radiusPlus1; _i5++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack = stack.next;
}
var rInSum = 0,
gInSum = 0,
bInSum = 0;
for (var _i6 = 1; _i6 < radiusPlus1; _i6++) {
p = yi + ((widthMinus1 < _i6 ? widthMinus1 : _i6) << 2);
rSum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - _i6);
gSum += (stack.g = pg = pixels[p + 1]) * rbs;
bSum += (stack.b = pb = pixels[p + 2]) * rbs;
rInSum += pr;
gInSum += pg;
bInSum += pb;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (var x = 0; x < width; x++) {
pixels[yi] = rSum * mulSum >>> shgSum;
pixels[yi + 1] = gSum * mulSum >>> shgSum;
pixels[yi + 2] = bSum * mulSum >>> shgSum;
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
rInSum += stackIn.r = pixels[p];
gInSum += stackIn.g = pixels[p + 1];
bInSum += stackIn.b = pixels[p + 2];
rSum += rInSum;
gSum += gInSum;
bSum += bInSum;
stackIn = stackIn.next;
rOutSum += pr = stackOut.r;
gOutSum += pg = stackOut.g;
bOutSum += pb = stackOut.b;
rInSum -= pr;
gInSum -= pg;
bInSum -= pb;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (var _x2 = 0; _x2 < width; _x2++) {
yi = _x2 << 2;
var _pr2 = pixels[yi],
_pg2 = pixels[yi + 1],
_pb2 = pixels[yi + 2],
_rOutSum2 = radiusPlus1 * _pr2,
_gOutSum2 = radiusPlus1 * _pg2,
_bOutSum2 = radiusPlus1 * _pb2,
_rSum2 = sumFactor * _pr2,
_gSum2 = sumFactor * _pg2,
_bSum2 = sumFactor * _pb2;
stack = stackStart;
for (var _i7 = 0; _i7 < radiusPlus1; _i7++) {
stack.r = _pr2;
stack.g = _pg2;
stack.b = _pb2;
stack = stack.next;
}
var _rInSum2 = 0,
_gInSum2 = 0,
_bInSum2 = 0;
for (var _i8 = 1, yp = width; _i8 <= radius; _i8++) {
yi = yp + _x2 << 2;
_rSum2 += (stack.r = _pr2 = pixels[yi]) * (rbs = radiusPlus1 - _i8);
_gSum2 += (stack.g = _pg2 = pixels[yi + 1]) * rbs;
_bSum2 += (stack.b = _pb2 = pixels[yi + 2]) * rbs;
_rInSum2 += _pr2;
_gInSum2 += _pg2;
_bInSum2 += _pb2;
stack = stack.next;
if (_i8 < heightMinus1) {
yp += width;
}
}
yi = _x2;
stackIn = stackStart;
stackOut = stackEnd;
for (var _y2 = 0; _y2 < height; _y2++) {
p = yi << 2;
pixels[p] = _rSum2 * mulSum >>> shgSum;
pixels[p + 1] = _gSum2 * mulSum >>> shgSum;
pixels[p + 2] = _bSum2 * mulSum >>> shgSum;
_rSum2 -= _rOutSum2;
_gSum2 -= _gOutSum2;
_bSum2 -= _bOutSum2;
_rOutSum2 -= stackIn.r;
_gOutSum2 -= stackIn.g;
_bOutSum2 -= stackIn.b;
p = _x2 + ((p = _y2 + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
_rSum2 += _rInSum2 += stackIn.r = pixels[p];
_gSum2 += _gInSum2 += stackIn.g = pixels[p + 1];
_bSum2 += _bInSum2 += stackIn.b = pixels[p + 2];
stackIn = stackIn.next;
_rOutSum2 += _pr2 = stackOut.r;
_gOutSum2 += _pg2 = stackOut.g;
_bOutSum2 += _pb2 = stackOut.b;
_rInSum2 -= _pr2;
_gInSum2 -= _pg2;
_bInSum2 -= _pb2;
stackOut = stackOut.next;
yi += width;
}
}
return imageData;
}
/**
*
*/
var BlurStack =
/**
* Set properties.
*/
function BlurStack() {
_classCallCheck(this, BlurStack);
this.r = 0;
this.g = 0;
this.b = 0;
this.a = 0;
this.next = null;
};
export { BlurStack, processCanvasRGB as canvasRGB, processCanvasRGBA as canvasRGBA, processImage as image, processImageDataRGB as imageDataRGB, processImageDataRGBA as imageDataRGBA };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,654 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.StackBlur = {}));
}(this, (function (exports) { 'use strict';
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
/* eslint-disable no-bitwise -- used for calculations */
/* eslint-disable unicorn/prefer-query-selector -- aiming at
backward-compatibility */
/**
* StackBlur - a fast almost Gaussian Blur For Canvas
*
* 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:
* {@link https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript}.
*
* @module StackBlur
* @author Mario Klingemann
* Contact: mario@quasimondo.com
* Website: {@link http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html}
* Twitter: @quasimondo
*
* @copyright (c) 2010 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.
*/
var mulTable = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259];
var shgTable = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24];
/**
* @param {string|HTMLImageElement} img
* @param {string|HTMLCanvasElement} canvas
* @param {Float} radius
* @param {boolean} blurAlphaChannel
* @param {boolean} useOffset
* @param {boolean} skipStyles
* @returns {undefined}
*/
function processImage(img, canvas, radius, blurAlphaChannel, useOffset, skipStyles) {
if (typeof img === 'string') {
img = document.getElementById(img);
}
if (!img || Object.prototype.toString.call(img).slice(8, -1) === 'HTMLImageElement' && !('naturalWidth' in img)) {
return;
}
var dimensionType = useOffset ? 'offset' : 'natural';
var w = img[dimensionType + 'Width'];
var h = img[dimensionType + 'Height']; // add ImageBitmap support,can blur texture source
if (Object.prototype.toString.call(img).slice(8, -1) === 'ImageBitmap') {
w = img.width;
h = img.height;
}
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!canvas || !('getContext' in canvas)) {
return;
}
if (!skipStyles) {
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
}
canvas.width = w;
canvas.height = h;
var context = canvas.getContext('2d');
context.clearRect(0, 0, w, h);
context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, w, h);
if (isNaN(radius) || radius < 1) {
return;
}
if (blurAlphaChannel) {
processCanvasRGBA(canvas, 0, 0, w, h, radius);
} else {
processCanvasRGB(canvas, 0, 0, w, h, radius);
}
}
/**
* @param {string|HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @throws {Error|TypeError}
* @returns {ImageData} See {@link https://html.spec.whatwg.org/multipage/canvas.html#imagedata}
*/
function getImageDataFromCanvas(canvas, topX, topY, width, height) {
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!canvas || _typeof(canvas) !== 'object' || !('getContext' in canvas)) {
throw new TypeError('Expecting canvas with `getContext` method ' + 'in processCanvasRGB(A) calls!');
}
var context = canvas.getContext('2d');
try {
return context.getImageData(topX, topY, width, height);
} catch (e) {
throw new Error('unable to access image data: ' + e);
}
}
/**
* @param {HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {undefined}
*/
function processCanvasRGBA(canvas, topX, topY, width, height, radius) {
if (isNaN(radius) || radius < 1) {
return;
}
radius |= 0;
var imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
imageData = processImageDataRGBA(imageData, topX, topY, width, height, radius);
canvas.getContext('2d').putImageData(imageData, topX, topY);
}
/**
* @param {ImageData} imageData
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {ImageData}
*/
function processImageDataRGBA(imageData, topX, topY, width, height, radius) {
var pixels = imageData.data;
var div = 2 * radius + 1; // const w4 = width << 2;
var widthMinus1 = width - 1;
var heightMinus1 = height - 1;
var radiusPlus1 = radius + 1;
var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
var stackStart = new BlurStack();
var stack = stackStart;
var stackEnd;
for (var i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i === radiusPlus1) {
stackEnd = stack;
}
}
stack.next = stackStart;
var stackIn = null,
stackOut = null,
yw = 0,
yi = 0;
var mulSum = mulTable[radius];
var shgSum = shgTable[radius];
for (var y = 0; y < height; y++) {
stack = stackStart;
var pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
pa = pixels[yi + 3];
for (var _i = 0; _i < radiusPlus1; _i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack.a = pa;
stack = stack.next;
}
var rInSum = 0,
gInSum = 0,
bInSum = 0,
aInSum = 0,
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
aOutSum = radiusPlus1 * pa,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb,
aSum = sumFactor * pa;
for (var _i2 = 1; _i2 < radiusPlus1; _i2++) {
var p = yi + ((widthMinus1 < _i2 ? widthMinus1 : _i2) << 2);
var r = pixels[p],
g = pixels[p + 1],
b = pixels[p + 2],
a = pixels[p + 3];
var rbs = radiusPlus1 - _i2;
rSum += (stack.r = r) * rbs;
gSum += (stack.g = g) * rbs;
bSum += (stack.b = b) * rbs;
aSum += (stack.a = a) * rbs;
rInSum += r;
gInSum += g;
bInSum += b;
aInSum += a;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (var x = 0; x < width; x++) {
var paInitial = aSum * mulSum >>> shgSum;
pixels[yi + 3] = paInitial;
if (paInitial !== 0) {
var _a2 = 255 / paInitial;
pixels[yi] = (rSum * mulSum >>> shgSum) * _a2;
pixels[yi + 1] = (gSum * mulSum >>> shgSum) * _a2;
pixels[yi + 2] = (bSum * mulSum >>> shgSum) * _a2;
} else {
pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
}
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
aSum -= aOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
aOutSum -= stackIn.a;
var _p = x + radius + 1;
_p = yw + (_p < widthMinus1 ? _p : widthMinus1) << 2;
rInSum += stackIn.r = pixels[_p];
gInSum += stackIn.g = pixels[_p + 1];
bInSum += stackIn.b = pixels[_p + 2];
aInSum += stackIn.a = pixels[_p + 3];
rSum += rInSum;
gSum += gInSum;
bSum += bInSum;
aSum += aInSum;
stackIn = stackIn.next;
var _stackOut = stackOut,
_r = _stackOut.r,
_g = _stackOut.g,
_b = _stackOut.b,
_a = _stackOut.a;
rOutSum += _r;
gOutSum += _g;
bOutSum += _b;
aOutSum += _a;
rInSum -= _r;
gInSum -= _g;
bInSum -= _b;
aInSum -= _a;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (var _x = 0; _x < width; _x++) {
yi = _x << 2;
var _pr = pixels[yi],
_pg = pixels[yi + 1],
_pb = pixels[yi + 2],
_pa = pixels[yi + 3],
_rOutSum = radiusPlus1 * _pr,
_gOutSum = radiusPlus1 * _pg,
_bOutSum = radiusPlus1 * _pb,
_aOutSum = radiusPlus1 * _pa,
_rSum = sumFactor * _pr,
_gSum = sumFactor * _pg,
_bSum = sumFactor * _pb,
_aSum = sumFactor * _pa;
stack = stackStart;
for (var _i3 = 0; _i3 < radiusPlus1; _i3++) {
stack.r = _pr;
stack.g = _pg;
stack.b = _pb;
stack.a = _pa;
stack = stack.next;
}
var yp = width;
var _gInSum = 0,
_bInSum = 0,
_aInSum = 0,
_rInSum = 0;
for (var _i4 = 1; _i4 <= radius; _i4++) {
yi = yp + _x << 2;
var _rbs = radiusPlus1 - _i4;
_rSum += (stack.r = _pr = pixels[yi]) * _rbs;
_gSum += (stack.g = _pg = pixels[yi + 1]) * _rbs;
_bSum += (stack.b = _pb = pixels[yi + 2]) * _rbs;
_aSum += (stack.a = _pa = pixels[yi + 3]) * _rbs;
_rInSum += _pr;
_gInSum += _pg;
_bInSum += _pb;
_aInSum += _pa;
stack = stack.next;
if (_i4 < heightMinus1) {
yp += width;
}
}
yi = _x;
stackIn = stackStart;
stackOut = stackEnd;
for (var _y = 0; _y < height; _y++) {
var _p2 = yi << 2;
pixels[_p2 + 3] = _pa = _aSum * mulSum >>> shgSum;
if (_pa > 0) {
_pa = 255 / _pa;
pixels[_p2] = (_rSum * mulSum >>> shgSum) * _pa;
pixels[_p2 + 1] = (_gSum * mulSum >>> shgSum) * _pa;
pixels[_p2 + 2] = (_bSum * mulSum >>> shgSum) * _pa;
} else {
pixels[_p2] = pixels[_p2 + 1] = pixels[_p2 + 2] = 0;
}
_rSum -= _rOutSum;
_gSum -= _gOutSum;
_bSum -= _bOutSum;
_aSum -= _aOutSum;
_rOutSum -= stackIn.r;
_gOutSum -= stackIn.g;
_bOutSum -= stackIn.b;
_aOutSum -= stackIn.a;
_p2 = _x + ((_p2 = _y + radiusPlus1) < heightMinus1 ? _p2 : heightMinus1) * width << 2;
_rSum += _rInSum += stackIn.r = pixels[_p2];
_gSum += _gInSum += stackIn.g = pixels[_p2 + 1];
_bSum += _bInSum += stackIn.b = pixels[_p2 + 2];
_aSum += _aInSum += stackIn.a = pixels[_p2 + 3];
stackIn = stackIn.next;
_rOutSum += _pr = stackOut.r;
_gOutSum += _pg = stackOut.g;
_bOutSum += _pb = stackOut.b;
_aOutSum += _pa = stackOut.a;
_rInSum -= _pr;
_gInSum -= _pg;
_bInSum -= _pb;
_aInSum -= _pa;
stackOut = stackOut.next;
yi += width;
}
}
return imageData;
}
/**
* @param {HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {undefined}
*/
function processCanvasRGB(canvas, topX, topY, width, height, radius) {
if (isNaN(radius) || radius < 1) {
return;
}
radius |= 0;
var imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
imageData = processImageDataRGB(imageData, topX, topY, width, height, radius);
canvas.getContext('2d').putImageData(imageData, topX, topY);
}
/**
* @param {ImageData} imageData
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {ImageData}
*/
function processImageDataRGB(imageData, topX, topY, width, height, radius) {
var pixels = imageData.data;
var div = 2 * radius + 1; // const w4 = width << 2;
var widthMinus1 = width - 1;
var heightMinus1 = height - 1;
var radiusPlus1 = radius + 1;
var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
var stackStart = new BlurStack();
var stack = stackStart;
var stackEnd;
for (var i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i === radiusPlus1) {
stackEnd = stack;
}
}
stack.next = stackStart;
var stackIn = null;
var stackOut = null;
var mulSum = mulTable[radius];
var shgSum = shgTable[radius];
var p, rbs;
var yw = 0,
yi = 0;
for (var y = 0; y < height; y++) {
var pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb;
stack = stackStart;
for (var _i5 = 0; _i5 < radiusPlus1; _i5++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack = stack.next;
}
var rInSum = 0,
gInSum = 0,
bInSum = 0;
for (var _i6 = 1; _i6 < radiusPlus1; _i6++) {
p = yi + ((widthMinus1 < _i6 ? widthMinus1 : _i6) << 2);
rSum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - _i6);
gSum += (stack.g = pg = pixels[p + 1]) * rbs;
bSum += (stack.b = pb = pixels[p + 2]) * rbs;
rInSum += pr;
gInSum += pg;
bInSum += pb;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (var x = 0; x < width; x++) {
pixels[yi] = rSum * mulSum >>> shgSum;
pixels[yi + 1] = gSum * mulSum >>> shgSum;
pixels[yi + 2] = bSum * mulSum >>> shgSum;
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
rInSum += stackIn.r = pixels[p];
gInSum += stackIn.g = pixels[p + 1];
bInSum += stackIn.b = pixels[p + 2];
rSum += rInSum;
gSum += gInSum;
bSum += bInSum;
stackIn = stackIn.next;
rOutSum += pr = stackOut.r;
gOutSum += pg = stackOut.g;
bOutSum += pb = stackOut.b;
rInSum -= pr;
gInSum -= pg;
bInSum -= pb;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (var _x2 = 0; _x2 < width; _x2++) {
yi = _x2 << 2;
var _pr2 = pixels[yi],
_pg2 = pixels[yi + 1],
_pb2 = pixels[yi + 2],
_rOutSum2 = radiusPlus1 * _pr2,
_gOutSum2 = radiusPlus1 * _pg2,
_bOutSum2 = radiusPlus1 * _pb2,
_rSum2 = sumFactor * _pr2,
_gSum2 = sumFactor * _pg2,
_bSum2 = sumFactor * _pb2;
stack = stackStart;
for (var _i7 = 0; _i7 < radiusPlus1; _i7++) {
stack.r = _pr2;
stack.g = _pg2;
stack.b = _pb2;
stack = stack.next;
}
var _rInSum2 = 0,
_gInSum2 = 0,
_bInSum2 = 0;
for (var _i8 = 1, yp = width; _i8 <= radius; _i8++) {
yi = yp + _x2 << 2;
_rSum2 += (stack.r = _pr2 = pixels[yi]) * (rbs = radiusPlus1 - _i8);
_gSum2 += (stack.g = _pg2 = pixels[yi + 1]) * rbs;
_bSum2 += (stack.b = _pb2 = pixels[yi + 2]) * rbs;
_rInSum2 += _pr2;
_gInSum2 += _pg2;
_bInSum2 += _pb2;
stack = stack.next;
if (_i8 < heightMinus1) {
yp += width;
}
}
yi = _x2;
stackIn = stackStart;
stackOut = stackEnd;
for (var _y2 = 0; _y2 < height; _y2++) {
p = yi << 2;
pixels[p] = _rSum2 * mulSum >>> shgSum;
pixels[p + 1] = _gSum2 * mulSum >>> shgSum;
pixels[p + 2] = _bSum2 * mulSum >>> shgSum;
_rSum2 -= _rOutSum2;
_gSum2 -= _gOutSum2;
_bSum2 -= _bOutSum2;
_rOutSum2 -= stackIn.r;
_gOutSum2 -= stackIn.g;
_bOutSum2 -= stackIn.b;
p = _x2 + ((p = _y2 + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
_rSum2 += _rInSum2 += stackIn.r = pixels[p];
_gSum2 += _gInSum2 += stackIn.g = pixels[p + 1];
_bSum2 += _bInSum2 += stackIn.b = pixels[p + 2];
stackIn = stackIn.next;
_rOutSum2 += _pr2 = stackOut.r;
_gOutSum2 += _pg2 = stackOut.g;
_bOutSum2 += _pb2 = stackOut.b;
_rInSum2 -= _pr2;
_gInSum2 -= _pg2;
_bInSum2 -= _pb2;
stackOut = stackOut.next;
yi += width;
}
}
return imageData;
}
/**
*
*/
var BlurStack =
/**
* Set properties.
*/
function BlurStack() {
_classCallCheck(this, BlurStack);
this.r = 0;
this.g = 0;
this.b = 0;
this.a = 0;
this.next = null;
};
exports.BlurStack = BlurStack;
exports.canvasRGB = processCanvasRGB;
exports.canvasRGBA = processCanvasRGBA;
exports.image = processImage;
exports.imageDataRGB = processImageDataRGB;
exports.imageDataRGBA = processImageDataRGBA;
Object.defineProperty(exports, '__esModule', { value: true });
})));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,52 @@
export class BlurStack {
r: number;
g: number;
b: number;
a: number;
next: BlurStack;
}
export function image(
img: HTMLImageElement | string,
canvas: HTMLCanvasElement | string,
radius: number,
blurAlphaChannel?: boolean,
useOffset?: boolean,
skipStyles?: boolean,
): void;
export function canvasRGBA(
canvas: HTMLCanvasElement,
topX: number,
topY: number,
width: number,
height: number,
radius: number
): void;
export function canvasRGB(
canvas: HTMLCanvasElement,
topX: number,
topY: number,
width: number,
height: number,
radius: number
): void;
export function imageDataRGBA(
data: ImageData,
topX: number,
topY: number,
width: number,
height: number,
radius: number
): ImageData;
export function imageDataRGB(
data: ImageData,
topX: number,
topY: number,
width: number,
height: number,
radius: number
): ImageData;

View File

@@ -0,0 +1,71 @@
{
"name": "stackblur-canvas",
"version": "2.7.0",
"description": "Fast and almost Gaussian blur by Mario Klingemann",
"main": "dist/stackblur.js",
"module": "dist/stackblur-es.js",
"browserslist": {
"target": "cover 100%"
},
"scripts": {
"prepublishOnly": "pnpm i",
"start": "open-cli http://localhost:8081/demo/ && http-server -p 8081",
"eslint": "eslint --ext=js,md,html .",
"rollup": "rollup -c",
"docs": "rm -rf docs/jsdoc/*;jsdoc --pedantic -c docs/jsdoc-config.json src",
"open-docs": "npm run docs && open-cli http://localhost:8081/docs/jsdoc/ && http-server -p 8081",
"test": "npm run eslint && npm run rollup && echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/flozz/StackBlur.git"
},
"keywords": [
"stackblur",
"blur",
"canvas",
"gaussian"
],
"author": "Mario Klingemann",
"homepage": "http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html",
"contributors": [
"Brett Zamir"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/flozz/StackBlur/issues"
},
"engines": {
"node": ">=0.1.14"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/preset-env": "^7.12.16",
"@brettz9/eslint-plugin": "^1.0.3",
"@rollup/plugin-babel": "^5.3.0",
"eslint": "^7.20.0",
"eslint-config-ash-nazg": "29.0.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-array-func": "^3.1.7",
"eslint-plugin-compat": "^3.9.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsdoc": "^32.0.1",
"eslint-plugin-markdown": "^2.0.0",
"eslint-plugin-no-unsanitized": "^3.1.4",
"eslint-plugin-no-use-extend-native": "^0.5.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-radar": "^0.2.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-unicorn": "^28.0.1",
"http-server": "^0.12.3",
"jsdoc": "^3.6.5",
"open-cli": "^6.0.1",
"rollup": "2.39.0",
"rollup-plugin-re": "^1.0.7",
"rollup-plugin-terser": "^7.0.2"
},
"dependencies": {}
}

View File

@@ -0,0 +1,710 @@
/* eslint-disable no-bitwise -- used for calculations */
/* eslint-disable unicorn/prefer-query-selector -- aiming at
backward-compatibility */
/**
* StackBlur - a fast almost Gaussian Blur For Canvas
*
* 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:
* {@link https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript}.
*
* @module StackBlur
* @author Mario Klingemann
* Contact: mario@quasimondo.com
* Website: {@link http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html}
* Twitter: @quasimondo
*
* @copyright (c) 2010 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.
*/
const mulTable = [
512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292,
512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292,
273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259,
496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292,
282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373,
364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259,
507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381,
374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292,
287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461,
454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373,
368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309,
305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259,
257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442,
437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381,
377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332,
329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,
289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259
];
const shgTable = [
9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
];
/**
* @param {string|HTMLImageElement} img
* @param {string|HTMLCanvasElement} canvas
* @param {Float} radius
* @param {boolean} blurAlphaChannel
* @param {boolean} useOffset
* @param {boolean} skipStyles
* @returns {undefined}
*/
function processImage (
img, canvas, radius, blurAlphaChannel, useOffset, skipStyles
) {
if (typeof img === 'string') {
img = document.getElementById(img);
}
if (
!img ||
(Object.prototype.toString.call(img).slice(8, -1) ===
'HTMLImageElement' && !('naturalWidth' in img))
) {
return;
}
const dimensionType = useOffset ? 'offset' : 'natural';
let w = img[dimensionType + 'Width'];
let h = img[dimensionType + 'Height'];
// add ImageBitmap support,can blur texture source
if (Object.prototype.toString.call(img).slice(8, -1) === 'ImageBitmap') {
w = img.width;
h = img.height;
}
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!canvas || !('getContext' in canvas)) {
return;
}
if (!skipStyles) {
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
}
canvas.width = w;
canvas.height = h;
const context = canvas.getContext('2d');
context.clearRect(0, 0, w, h);
context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, w, h);
if (isNaN(radius) || radius < 1) { return; }
if (blurAlphaChannel) {
processCanvasRGBA(canvas, 0, 0, w, h, radius);
} else {
processCanvasRGB(canvas, 0, 0, w, h, radius);
}
}
/**
* @param {string|HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @throws {Error|TypeError}
* @returns {ImageData} See {@link https://html.spec.whatwg.org/multipage/canvas.html#imagedata}
*/
function getImageDataFromCanvas (canvas, topX, topY, width, height) {
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!canvas || typeof canvas !== 'object' || !('getContext' in canvas)) {
throw new TypeError(
'Expecting canvas with `getContext` method ' +
'in processCanvasRGB(A) calls!'
);
}
const context = canvas.getContext('2d');
try {
return context.getImageData(topX, topY, width, height);
} catch (e) {
throw new Error('unable to access image data: ' + e);
}
}
/**
* @param {HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {undefined}
*/
function processCanvasRGBA (canvas, topX, topY, width, height, radius) {
if (isNaN(radius) || radius < 1) { return; }
radius |= 0;
let imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
imageData = processImageDataRGBA(
imageData, topX, topY, width, height, radius
);
canvas.getContext('2d').putImageData(imageData, topX, topY);
}
/**
* @param {ImageData} imageData
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {ImageData}
*/
function processImageDataRGBA (imageData, topX, topY, width, height, radius) {
const pixels = imageData.data;
const div = 2 * radius + 1;
// const w4 = width << 2;
const widthMinus1 = width - 1;
const heightMinus1 = height - 1;
const radiusPlus1 = radius + 1;
const sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
const stackStart = new BlurStack();
let stack = stackStart;
let stackEnd;
for (let i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i === radiusPlus1) {
stackEnd = stack;
}
}
stack.next = stackStart;
let stackIn = null,
stackOut = null,
yw = 0,
yi = 0;
const mulSum = mulTable[radius];
const shgSum = shgTable[radius];
for (let y = 0; y < height; y++) {
stack = stackStart;
const pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
pa = pixels[yi + 3];
for (let i = 0; i < radiusPlus1; i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack.a = pa;
stack = stack.next;
}
let rInSum = 0, gInSum = 0, bInSum = 0, aInSum = 0,
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
aOutSum = radiusPlus1 * pa,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb,
aSum = sumFactor * pa;
for (let i = 1; i < radiusPlus1; i++) {
const p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
const r = pixels[p],
g = pixels[p + 1],
b = pixels[p + 2],
a = pixels[p + 3];
const rbs = radiusPlus1 - i;
rSum += (stack.r = r) * rbs;
gSum += (stack.g = g) * rbs;
bSum += (stack.b = b) * rbs;
aSum += (stack.a = a) * rbs;
rInSum += r;
gInSum += g;
bInSum += b;
aInSum += a;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (let x = 0; x < width; x++) {
const paInitial = (aSum * mulSum) >>> shgSum;
pixels[yi + 3] = paInitial;
if (paInitial !== 0) {
const a = 255 / paInitial;
pixels[yi] = ((rSum * mulSum) >>> shgSum) * a;
pixels[yi + 1] = ((gSum * mulSum) >>> shgSum) * a;
pixels[yi + 2] = ((bSum * mulSum) >>> shgSum) * a;
} else {
pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
}
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
aSum -= aOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
aOutSum -= stackIn.a;
let p = x + radius + 1;
p = (yw + (p < widthMinus1
? p
: widthMinus1)) << 2;
rInSum += (stackIn.r = pixels[p]);
gInSum += (stackIn.g = pixels[p + 1]);
bInSum += (stackIn.b = pixels[p + 2]);
aInSum += (stackIn.a = pixels[p + 3]);
rSum += rInSum;
gSum += gInSum;
bSum += bInSum;
aSum += aInSum;
stackIn = stackIn.next;
const {r, g, b, a} = stackOut;
rOutSum += r;
gOutSum += g;
bOutSum += b;
aOutSum += a;
rInSum -= r;
gInSum -= g;
bInSum -= b;
aInSum -= a;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (let x = 0; x < width; x++) {
yi = x << 2;
let pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
pa = pixels[yi + 3],
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
aOutSum = radiusPlus1 * pa,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb,
aSum = sumFactor * pa;
stack = stackStart;
for (let i = 0; i < radiusPlus1; i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack.a = pa;
stack = stack.next;
}
let yp = width;
let gInSum = 0, bInSum = 0, aInSum = 0, rInSum = 0;
for (let i = 1; i <= radius; i++) {
yi = (yp + x) << 2;
const rbs = radiusPlus1 - i;
rSum += (stack.r = (pr = pixels[yi])) * rbs;
gSum += (stack.g = (pg = pixels[yi + 1])) * rbs;
bSum += (stack.b = (pb = pixels[yi + 2])) * rbs;
aSum += (stack.a = (pa = pixels[yi + 3])) * rbs;
rInSum += pr;
gInSum += pg;
bInSum += pb;
aInSum += pa;
stack = stack.next;
if (i < heightMinus1) {
yp += width;
}
}
yi = x;
stackIn = stackStart;
stackOut = stackEnd;
for (let y = 0; y < height; y++) {
let p = yi << 2;
pixels[p + 3] = pa = (aSum * mulSum) >>> shgSum;
if (pa > 0) {
pa = 255 / pa;
pixels[p] = ((rSum * mulSum) >>> shgSum) * pa;
pixels[p + 1] = ((gSum * mulSum) >>> shgSum) * pa;
pixels[p + 2] = ((bSum * mulSum) >>> shgSum) * pa;
} else {
pixels[p] = pixels[p + 1] = pixels[p + 2] = 0;
}
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
aSum -= aOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
aOutSum -= stackIn.a;
p = (x + (
((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) *
width
)) << 2;
rSum += (rInSum += (stackIn.r = pixels[p]));
gSum += (gInSum += (stackIn.g = pixels[p + 1]));
bSum += (bInSum += (stackIn.b = pixels[p + 2]));
aSum += (aInSum += (stackIn.a = pixels[p + 3]));
stackIn = stackIn.next;
rOutSum += (pr = stackOut.r);
gOutSum += (pg = stackOut.g);
bOutSum += (pb = stackOut.b);
aOutSum += (pa = stackOut.a);
rInSum -= pr;
gInSum -= pg;
bInSum -= pb;
aInSum -= pa;
stackOut = stackOut.next;
yi += width;
}
}
return imageData;
}
/**
* @param {HTMLCanvasElement} canvas
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {undefined}
*/
function processCanvasRGB (canvas, topX, topY, width, height, radius) {
if (isNaN(radius) || radius < 1) { return; }
radius |= 0;
let imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
imageData = processImageDataRGB(
imageData, topX, topY, width, height, radius
);
canvas.getContext('2d').putImageData(imageData, topX, topY);
}
/**
* @param {ImageData} imageData
* @param {Integer} topX
* @param {Integer} topY
* @param {Integer} width
* @param {Integer} height
* @param {Float} radius
* @returns {ImageData}
*/
function processImageDataRGB (imageData, topX, topY, width, height, radius) {
const pixels = imageData.data;
const div = 2 * radius + 1;
// const w4 = width << 2;
const widthMinus1 = width - 1;
const heightMinus1 = height - 1;
const radiusPlus1 = radius + 1;
const sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
const stackStart = new BlurStack();
let stack = stackStart;
let stackEnd;
for (let i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i === radiusPlus1) {
stackEnd = stack;
}
}
stack.next = stackStart;
let stackIn = null;
let stackOut = null;
const mulSum = mulTable[radius];
const shgSum = shgTable[radius];
let p, rbs;
let yw = 0, yi = 0;
for (let y = 0; y < height; y++) {
let pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb;
stack = stackStart;
for (let i = 0; i < radiusPlus1; i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack = stack.next;
}
let rInSum = 0, gInSum = 0, bInSum = 0;
for (let i = 1; i < radiusPlus1; i++) {
p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
rSum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i);
gSum += (stack.g = (pg = pixels[p + 1])) * rbs;
bSum += (stack.b = (pb = pixels[p + 2])) * rbs;
rInSum += pr;
gInSum += pg;
bInSum += pb;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (let x = 0; x < width; x++) {
pixels[yi] = (rSum * mulSum) >>> shgSum;
pixels[yi + 1] = (gSum * mulSum) >>> shgSum;
pixels[yi + 2] = (bSum * mulSum) >>> shgSum;
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
p = (yw + (
(p = x + radius + 1) < widthMinus1 ? p : widthMinus1
)) << 2;
rInSum += (stackIn.r = pixels[p]);
gInSum += (stackIn.g = pixels[p + 1]);
bInSum += (stackIn.b = pixels[p + 2]);
rSum += rInSum;
gSum += gInSum;
bSum += bInSum;
stackIn = stackIn.next;
rOutSum += (pr = stackOut.r);
gOutSum += (pg = stackOut.g);
bOutSum += (pb = stackOut.b);
rInSum -= pr;
gInSum -= pg;
bInSum -= pb;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (let x = 0; x < width; x++) {
yi = x << 2;
let pr = pixels[yi],
pg = pixels[yi + 1],
pb = pixels[yi + 2],
rOutSum = radiusPlus1 * pr,
gOutSum = radiusPlus1 * pg,
bOutSum = radiusPlus1 * pb,
rSum = sumFactor * pr,
gSum = sumFactor * pg,
bSum = sumFactor * pb;
stack = stackStart;
for (let i = 0; i < radiusPlus1; i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack = stack.next;
}
let rInSum = 0, gInSum = 0, bInSum = 0;
for (let i = 1, yp = width; i <= radius; i++) {
yi = (yp + x) << 2;
rSum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i);
gSum += (stack.g = (pg = pixels[yi + 1])) * rbs;
bSum += (stack.b = (pb = pixels[yi + 2])) * rbs;
rInSum += pr;
gInSum += pg;
bInSum += pb;
stack = stack.next;
if (i < heightMinus1) {
yp += width;
}
}
yi = x;
stackIn = stackStart;
stackOut = stackEnd;
for (let y = 0; y < height; y++) {
p = yi << 2;
pixels[p] = (rSum * mulSum) >>> shgSum;
pixels[p + 1] = (gSum * mulSum) >>> shgSum;
pixels[p + 2] = (bSum * mulSum) >>> shgSum;
rSum -= rOutSum;
gSum -= gOutSum;
bSum -= bOutSum;
rOutSum -= stackIn.r;
gOutSum -= stackIn.g;
bOutSum -= stackIn.b;
p = (x + (
((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) *
width
)) << 2;
rSum += (rInSum += (stackIn.r = pixels[p]));
gSum += (gInSum += (stackIn.g = pixels[p + 1]));
bSum += (bInSum += (stackIn.b = pixels[p + 2]));
stackIn = stackIn.next;
rOutSum += (pr = stackOut.r);
gOutSum += (pg = stackOut.g);
bOutSum += (pb = stackOut.b);
rInSum -= pr;
gInSum -= pg;
bInSum -= pb;
stackOut = stackOut.next;
yi += width;
}
}
return imageData;
}
/**
*
*/
export class BlurStack {
/**
* Set properties.
*/
constructor () {
this.r = 0;
this.g = 0;
this.b = 0;
this.a = 0;
this.next = null;
}
}
export {
/**
* @function module:StackBlur.image
* @see module:StackBlur~processImage
*/
processImage as image,
/**
* @function module:StackBlur.canvasRGBA
* @see module:StackBlur~processCanvasRGBA
*/
processCanvasRGBA as canvasRGBA,
/**
* @function module:StackBlur.canvasRGB
* @see module:StackBlur~processCanvasRGB
*/
processCanvasRGB as canvasRGB,
/**
* @function module:StackBlur.imageDataRGBA
* @see module:StackBlur~processImageDataRGBA
*/
processImageDataRGBA as imageDataRGBA,
/**
* @function module:StackBlur.imageDataRGB
* @see module:StackBlur~processImageDataRGB
*/
processImageDataRGB as imageDataRGB
};