Source: stackblur.js

  1. /**
  2. * StackBlur - a fast almost Gaussian Blur For Canvas
  3. *
  4. * In case you find this class useful - especially in commercial projects -
  5. * I am not totally unhappy for a small donation to my PayPal account
  6. * mario@quasimondo.de
  7. *
  8. * Or support me on flattr:
  9. * {@link https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript}
  10. * @module StackBlur
  11. * @version 0.5
  12. * @author Mario Klingemann
  13. * Contact: mario@quasimondo.com
  14. * Website: {@link http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html}
  15. * Twitter: @quasimondo
  16. *
  17. * @copyright (c) 2010 Mario Klingemann
  18. *
  19. * Permission is hereby granted, free of charge, to any person
  20. * obtaining a copy of this software and associated documentation
  21. * files (the "Software"), to deal in the Software without
  22. * restriction, including without limitation the rights to use,
  23. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  24. * copies of the Software, and to permit persons to whom the
  25. * Software is furnished to do so, subject to the following
  26. * conditions:
  27. *
  28. * The above copyright notice and this permission notice shall be
  29. * included in all copies or substantial portions of the Software.
  30. *
  31. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  32. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  33. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  34. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  35. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  36. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  37. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  38. * OTHER DEALINGS IN THE SOFTWARE.
  39. */
  40. const mulTable = [
  41. 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512,
  42. 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512,
  43. 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456,
  44. 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512,
  45. 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328,
  46. 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456,
  47. 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335,
  48. 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512,
  49. 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405,
  50. 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328,
  51. 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271,
  52. 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456,
  53. 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388,
  54. 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335,
  55. 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292,
  56. 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259];
  57. const shgTable = [
  58. 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
  59. 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
  60. 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
  61. 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
  62. 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
  63. 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
  64. 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
  65. 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
  66. 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
  67. 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
  68. 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
  69. 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  70. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  71. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  72. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  73. 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24];
  74. /**
  75. * @param {string|HTMLImageElement} img
  76. * @param {string|HTMLCanvasElement} canvas
  77. * @param {Float} radius
  78. * @param {boolean} blurAlphaChannel
  79. * @returns {undefined}
  80. */
  81. function processImage (img, canvas, radius, blurAlphaChannel) {
  82. if (typeof img === 'string') {
  83. img = document.getElementById(img);
  84. }
  85. if (!img || !('naturalWidth' in img)) {
  86. return;
  87. }
  88. const w = img.naturalWidth;
  89. const h = img.naturalHeight;
  90. if (typeof canvas === 'string') {
  91. canvas = document.getElementById(canvas);
  92. }
  93. if (!canvas || !('getContext' in canvas)) {
  94. return;
  95. }
  96. canvas.style.width = w + 'px';
  97. canvas.style.height = h + 'px';
  98. canvas.width = w;
  99. canvas.height = h;
  100. const context = canvas.getContext('2d');
  101. context.clearRect(0, 0, w, h);
  102. context.drawImage(img, 0, 0);
  103. if (isNaN(radius) || radius < 1) { return; }
  104. if (blurAlphaChannel) {
  105. processCanvasRGBA(canvas, 0, 0, w, h, radius);
  106. } else {
  107. processCanvasRGB(canvas, 0, 0, w, h, radius);
  108. }
  109. }
  110. /**
  111. * @param {string|HTMLCanvasElement} canvas
  112. * @param {Integer} topX
  113. * @param {Integer} topY
  114. * @param {Integer} width
  115. * @param {Integer} height
  116. * @throws {Error|TypeError}
  117. * @returns {ImageData} See {@link https://html.spec.whatwg.org/multipage/canvas.html#imagedata}
  118. */
  119. function getImageDataFromCanvas (canvas, topX, topY, width, height) {
  120. if (typeof canvas === 'string') {
  121. canvas = document.getElementById(canvas);
  122. }
  123. if (!canvas || typeof canvas !== 'object' || !('getContext' in canvas)) {
  124. throw new TypeError('Expecting canvas with `getContext` method in processCanvasRGB(A) calls!');
  125. }
  126. const context = canvas.getContext('2d');
  127. try {
  128. return context.getImageData(topX, topY, width, height);
  129. } catch (e) {
  130. throw new Error('unable to access image data: ' + e);
  131. }
  132. }
  133. /**
  134. * @param {HTMLCanvasElement} canvas
  135. * @param {Integer} topX
  136. * @param {Integer} topY
  137. * @param {Integer} width
  138. * @param {Integer} height
  139. * @param {Float} radius
  140. * @returns {undefined}
  141. */
  142. function processCanvasRGBA (canvas, topX, topY, width, height, radius) {
  143. if (isNaN(radius) || radius < 1) { return; }
  144. radius |= 0;
  145. let imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
  146. imageData = processImageDataRGBA(imageData, topX, topY, width, height, radius);
  147. canvas.getContext('2d').putImageData(imageData, topX, topY);
  148. }
  149. /**
  150. * @param {ImageData} imageData
  151. * @param {Integer} topX
  152. * @param {Integer} topY
  153. * @param {Integer} width
  154. * @param {Integer} height
  155. * @param {Float} radius
  156. * @returns {ImageData}
  157. */
  158. function processImageDataRGBA (imageData, topX, topY, width, height, radius) {
  159. const pixels = imageData.data;
  160. let x, y, i, p, yp, yi, yw, rSum, gSum, bSum, aSum,
  161. rOutSum, gOutSum, bOutSum, aOutSum,
  162. rInSum, gInSum, bInSum, aInSum,
  163. pr, pg, pb, pa, rbs;
  164. const div = 2 * radius + 1;
  165. // const w4 = width << 2;
  166. const widthMinus1 = width - 1;
  167. const heightMinus1 = height - 1;
  168. const radiusPlus1 = radius + 1;
  169. const sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
  170. const stackStart = new BlurStack();
  171. let stack = stackStart;
  172. let stackEnd;
  173. for (i = 1; i < div; i++) {
  174. stack = stack.next = new BlurStack();
  175. if (i === radiusPlus1) {
  176. stackEnd = stack;
  177. }
  178. }
  179. stack.next = stackStart;
  180. let stackIn = null;
  181. let stackOut = null;
  182. yw = yi = 0;
  183. const mulSum = mulTable[radius];
  184. const shgSum = shgTable[radius];
  185. for (y = 0; y < height; y++) {
  186. rInSum = gInSum = bInSum = aInSum = rSum = gSum = bSum = aSum = 0;
  187. rOutSum = radiusPlus1 * (pr = pixels[yi]);
  188. gOutSum = radiusPlus1 * (pg = pixels[yi + 1]);
  189. bOutSum = radiusPlus1 * (pb = pixels[yi + 2]);
  190. aOutSum = radiusPlus1 * (pa = pixels[yi + 3]);
  191. rSum += sumFactor * pr;
  192. gSum += sumFactor * pg;
  193. bSum += sumFactor * pb;
  194. aSum += sumFactor * pa;
  195. stack = stackStart;
  196. for (i = 0; i < radiusPlus1; i++) {
  197. stack.r = pr;
  198. stack.g = pg;
  199. stack.b = pb;
  200. stack.a = pa;
  201. stack = stack.next;
  202. }
  203. for (i = 1; i < radiusPlus1; i++) {
  204. p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
  205. rSum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i);
  206. gSum += (stack.g = (pg = pixels[p + 1])) * rbs;
  207. bSum += (stack.b = (pb = pixels[p + 2])) * rbs;
  208. aSum += (stack.a = (pa = pixels[p + 3])) * rbs;
  209. rInSum += pr;
  210. gInSum += pg;
  211. bInSum += pb;
  212. aInSum += pa;
  213. stack = stack.next;
  214. }
  215. stackIn = stackStart;
  216. stackOut = stackEnd;
  217. for (x = 0; x < width; x++) {
  218. pixels[yi + 3] = pa = (aSum * mulSum) >> shgSum;
  219. if (pa !== 0) {
  220. pa = 255 / pa;
  221. pixels[yi] = ((rSum * mulSum) >> shgSum) * pa;
  222. pixels[yi + 1] = ((gSum * mulSum) >> shgSum) * pa;
  223. pixels[yi + 2] = ((bSum * mulSum) >> shgSum) * pa;
  224. } else {
  225. pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
  226. }
  227. rSum -= rOutSum;
  228. gSum -= gOutSum;
  229. bSum -= bOutSum;
  230. aSum -= aOutSum;
  231. rOutSum -= stackIn.r;
  232. gOutSum -= stackIn.g;
  233. bOutSum -= stackIn.b;
  234. aOutSum -= stackIn.a;
  235. p = (yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1)) << 2;
  236. rInSum += (stackIn.r = pixels[p]);
  237. gInSum += (stackIn.g = pixels[p + 1]);
  238. bInSum += (stackIn.b = pixels[p + 2]);
  239. aInSum += (stackIn.a = pixels[p + 3]);
  240. rSum += rInSum;
  241. gSum += gInSum;
  242. bSum += bInSum;
  243. aSum += aInSum;
  244. stackIn = stackIn.next;
  245. rOutSum += (pr = stackOut.r);
  246. gOutSum += (pg = stackOut.g);
  247. bOutSum += (pb = stackOut.b);
  248. aOutSum += (pa = stackOut.a);
  249. rInSum -= pr;
  250. gInSum -= pg;
  251. bInSum -= pb;
  252. aInSum -= pa;
  253. stackOut = stackOut.next;
  254. yi += 4;
  255. }
  256. yw += width;
  257. }
  258. for (x = 0; x < width; x++) {
  259. gInSum = bInSum = aInSum = rInSum = gSum = bSum = aSum = rSum = 0;
  260. yi = x << 2;
  261. rOutSum = radiusPlus1 * (pr = pixels[yi]);
  262. gOutSum = radiusPlus1 * (pg = pixels[yi + 1]);
  263. bOutSum = radiusPlus1 * (pb = pixels[yi + 2]);
  264. aOutSum = radiusPlus1 * (pa = pixels[yi + 3]);
  265. rSum += sumFactor * pr;
  266. gSum += sumFactor * pg;
  267. bSum += sumFactor * pb;
  268. aSum += sumFactor * pa;
  269. stack = stackStart;
  270. for (i = 0; i < radiusPlus1; i++) {
  271. stack.r = pr;
  272. stack.g = pg;
  273. stack.b = pb;
  274. stack.a = pa;
  275. stack = stack.next;
  276. }
  277. yp = width;
  278. for (i = 1; i <= radius; i++) {
  279. yi = (yp + x) << 2;
  280. rSum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i);
  281. gSum += (stack.g = (pg = pixels[yi + 1])) * rbs;
  282. bSum += (stack.b = (pb = pixels[yi + 2])) * rbs;
  283. aSum += (stack.a = (pa = pixels[yi + 3])) * rbs;
  284. rInSum += pr;
  285. gInSum += pg;
  286. bInSum += pb;
  287. aInSum += pa;
  288. stack = stack.next;
  289. if (i < heightMinus1) {
  290. yp += width;
  291. }
  292. }
  293. yi = x;
  294. stackIn = stackStart;
  295. stackOut = stackEnd;
  296. for (y = 0; y < height; y++) {
  297. p = yi << 2;
  298. pixels[p + 3] = pa = (aSum * mulSum) >> shgSum;
  299. if (pa > 0) {
  300. pa = 255 / pa;
  301. pixels[p] = ((rSum * mulSum) >> shgSum) * pa;
  302. pixels[p + 1] = ((gSum * mulSum) >> shgSum) * pa;
  303. pixels[p + 2] = ((bSum * mulSum) >> shgSum) * pa;
  304. } else {
  305. pixels[p] = pixels[p + 1] = pixels[p + 2] = 0;
  306. }
  307. rSum -= rOutSum;
  308. gSum -= gOutSum;
  309. bSum -= bOutSum;
  310. aSum -= aOutSum;
  311. rOutSum -= stackIn.r;
  312. gOutSum -= stackIn.g;
  313. bOutSum -= stackIn.b;
  314. aOutSum -= stackIn.a;
  315. p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2;
  316. rSum += (rInSum += (stackIn.r = pixels[p]));
  317. gSum += (gInSum += (stackIn.g = pixels[p + 1]));
  318. bSum += (bInSum += (stackIn.b = pixels[p + 2]));
  319. aSum += (aInSum += (stackIn.a = pixels[p + 3]));
  320. stackIn = stackIn.next;
  321. rOutSum += (pr = stackOut.r);
  322. gOutSum += (pg = stackOut.g);
  323. bOutSum += (pb = stackOut.b);
  324. aOutSum += (pa = stackOut.a);
  325. rInSum -= pr;
  326. gInSum -= pg;
  327. bInSum -= pb;
  328. aInSum -= pa;
  329. stackOut = stackOut.next;
  330. yi += width;
  331. }
  332. }
  333. return imageData;
  334. }
  335. /**
  336. * @param {HTMLCanvasElement} canvas
  337. * @param {Integer} topX
  338. * @param {Integer} topY
  339. * @param {Integer} width
  340. * @param {Integer} height
  341. * @param {Float} radius
  342. * @returns {undefined}
  343. */
  344. function processCanvasRGB (canvas, topX, topY, width, height, radius) {
  345. if (isNaN(radius) || radius < 1) { return; }
  346. radius |= 0;
  347. let imageData = getImageDataFromCanvas(canvas, topX, topY, width, height);
  348. imageData = processImageDataRGB(imageData, topX, topY, width, height, radius);
  349. canvas.getContext('2d').putImageData(imageData, topX, topY);
  350. }
  351. /**
  352. * @param {ImageData} imageData
  353. * @param {Integer} topX
  354. * @param {Integer} topY
  355. * @param {Integer} width
  356. * @param {Integer} height
  357. * @param {Float} radius
  358. * @returns {ImageData}
  359. */
  360. function processImageDataRGB (imageData, topX, topY, width, height, radius) {
  361. const pixels = imageData.data;
  362. let x, y, i, p, yp, yi, yw, rSum, gSum, bSum,
  363. rOutSum, gOutSum, bOutSum,
  364. rInSum, gInSum, bInSum,
  365. pr, pg, pb, rbs;
  366. const div = 2 * radius + 1;
  367. // const w4 = width << 2;
  368. const widthMinus1 = width - 1;
  369. const heightMinus1 = height - 1;
  370. const radiusPlus1 = radius + 1;
  371. const sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
  372. const stackStart = new BlurStack();
  373. let stack = stackStart;
  374. let stackEnd;
  375. for (i = 1; i < div; i++) {
  376. stack = stack.next = new BlurStack();
  377. if (i === radiusPlus1) {
  378. stackEnd = stack;
  379. }
  380. }
  381. stack.next = stackStart;
  382. let stackIn = null;
  383. let stackOut = null;
  384. yw = yi = 0;
  385. const mulSum = mulTable[radius];
  386. const shgSum = shgTable[radius];
  387. for (y = 0; y < height; y++) {
  388. rInSum = gInSum = bInSum = rSum = gSum = bSum = 0;
  389. rOutSum = radiusPlus1 * (pr = pixels[yi]);
  390. gOutSum = radiusPlus1 * (pg = pixels[yi + 1]);
  391. bOutSum = radiusPlus1 * (pb = pixels[yi + 2]);
  392. rSum += sumFactor * pr;
  393. gSum += sumFactor * pg;
  394. bSum += sumFactor * pb;
  395. stack = stackStart;
  396. for (i = 0; i < radiusPlus1; i++) {
  397. stack.r = pr;
  398. stack.g = pg;
  399. stack.b = pb;
  400. stack = stack.next;
  401. }
  402. for (i = 1; i < radiusPlus1; i++) {
  403. p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
  404. rSum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i);
  405. gSum += (stack.g = (pg = pixels[p + 1])) * rbs;
  406. bSum += (stack.b = (pb = pixels[p + 2])) * rbs;
  407. rInSum += pr;
  408. gInSum += pg;
  409. bInSum += pb;
  410. stack = stack.next;
  411. }
  412. stackIn = stackStart;
  413. stackOut = stackEnd;
  414. for (x = 0; x < width; x++) {
  415. pixels[yi] = (rSum * mulSum) >> shgSum;
  416. pixels[yi + 1] = (gSum * mulSum) >> shgSum;
  417. pixels[yi + 2] = (bSum * mulSum) >> shgSum;
  418. rSum -= rOutSum;
  419. gSum -= gOutSum;
  420. bSum -= bOutSum;
  421. rOutSum -= stackIn.r;
  422. gOutSum -= stackIn.g;
  423. bOutSum -= stackIn.b;
  424. p = (yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1)) << 2;
  425. rInSum += (stackIn.r = pixels[p]);
  426. gInSum += (stackIn.g = pixels[p + 1]);
  427. bInSum += (stackIn.b = pixels[p + 2]);
  428. rSum += rInSum;
  429. gSum += gInSum;
  430. bSum += bInSum;
  431. stackIn = stackIn.next;
  432. rOutSum += (pr = stackOut.r);
  433. gOutSum += (pg = stackOut.g);
  434. bOutSum += (pb = stackOut.b);
  435. rInSum -= pr;
  436. gInSum -= pg;
  437. bInSum -= pb;
  438. stackOut = stackOut.next;
  439. yi += 4;
  440. }
  441. yw += width;
  442. }
  443. for (x = 0; x < width; x++) {
  444. gInSum = bInSum = rInSum = gSum = bSum = rSum = 0;
  445. yi = x << 2;
  446. rOutSum = radiusPlus1 * (pr = pixels[yi]);
  447. gOutSum = radiusPlus1 * (pg = pixels[yi + 1]);
  448. bOutSum = radiusPlus1 * (pb = pixels[yi + 2]);
  449. rSum += sumFactor * pr;
  450. gSum += sumFactor * pg;
  451. bSum += sumFactor * pb;
  452. stack = stackStart;
  453. for (i = 0; i < radiusPlus1; i++) {
  454. stack.r = pr;
  455. stack.g = pg;
  456. stack.b = pb;
  457. stack = stack.next;
  458. }
  459. yp = width;
  460. for (i = 1; i <= radius; i++) {
  461. yi = (yp + x) << 2;
  462. rSum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i);
  463. gSum += (stack.g = (pg = pixels[yi + 1])) * rbs;
  464. bSum += (stack.b = (pb = pixels[yi + 2])) * rbs;
  465. rInSum += pr;
  466. gInSum += pg;
  467. bInSum += pb;
  468. stack = stack.next;
  469. if (i < heightMinus1) {
  470. yp += width;
  471. }
  472. }
  473. yi = x;
  474. stackIn = stackStart;
  475. stackOut = stackEnd;
  476. for (y = 0; y < height; y++) {
  477. p = yi << 2;
  478. pixels[p] = (rSum * mulSum) >> shgSum;
  479. pixels[p + 1] = (gSum * mulSum) >> shgSum;
  480. pixels[p + 2] = (bSum * mulSum) >> shgSum;
  481. rSum -= rOutSum;
  482. gSum -= gOutSum;
  483. bSum -= bOutSum;
  484. rOutSum -= stackIn.r;
  485. gOutSum -= stackIn.g;
  486. bOutSum -= stackIn.b;
  487. p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2;
  488. rSum += (rInSum += (stackIn.r = pixels[p]));
  489. gSum += (gInSum += (stackIn.g = pixels[p + 1]));
  490. bSum += (bInSum += (stackIn.b = pixels[p + 2]));
  491. stackIn = stackIn.next;
  492. rOutSum += (pr = stackOut.r);
  493. gOutSum += (pg = stackOut.g);
  494. bOutSum += (pb = stackOut.b);
  495. rInSum -= pr;
  496. gInSum -= pg;
  497. bInSum -= pb;
  498. stackOut = stackOut.next;
  499. yi += width;
  500. }
  501. }
  502. return imageData;
  503. }
  504. /**
  505. *
  506. */
  507. export class BlurStack {
  508. constructor () {
  509. this.r = 0;
  510. this.g = 0;
  511. this.b = 0;
  512. this.a = 0;
  513. this.next = null;
  514. }
  515. }
  516. export {
  517. /**
  518. * @function module:StackBlur.image
  519. * @see module:StackBlur~processImage
  520. */
  521. processImage as image,
  522. /**
  523. * @function module:StackBlur.canvasRGBA
  524. * @see module:StackBlur~processCanvasRGBA
  525. */
  526. processCanvasRGBA as canvasRGBA,
  527. /**
  528. * @function module:StackBlur.canvasRGB
  529. * @see module:StackBlur~processCanvasRGB
  530. */
  531. processCanvasRGB as canvasRGB,
  532. /**
  533. * @function module:StackBlur.imageDataRGBA
  534. * @see module:StackBlur~processImageDataRGBA
  535. */
  536. processImageDataRGBA as imageDataRGBA,
  537. /**
  538. * @function module:StackBlur.imageDataRGB
  539. * @see module:StackBlur~processImageDataRGB
  540. */
  541. processImageDataRGB as imageDataRGB
  542. };