Source: filters/BlurFilter.js

  1. import {Utils} from '../utils/Utils';
  2. /**
  3. *
  4. * @class
  5. * @memberof JC
  6. * @param {number} blurX x轴的模糊值
  7. * @param {number} blurY y轴的模糊值
  8. * @param {number} quality 模糊的质量,模糊计算会被递归多少次
  9. */
  10. function BlurFilter(blurX, blurY, quality) {
  11. if (Utils.isNumber(blurX) || blurX < 0) blurX = 0;
  12. if (Utils.isNumber(blurY) || blurY < 0) blurY = 0;
  13. if (Utils.isNumber(quality) || quality < 1) quality = 1;
  14. /**
  15. * x轴的模糊值
  16. * @property blurX
  17. * @default 0
  18. * @type Number
  19. **/
  20. this.blurX = blurX | 0;
  21. /**
  22. * y轴的模糊值
  23. * @property blurY
  24. * @default 0
  25. * @type Number
  26. **/
  27. this.blurY = blurY | 0;
  28. /**
  29. * 模糊的质量,模糊计算会被递归多少次
  30. * @property quality
  31. * @default 1
  32. * @type Number
  33. **/
  34. this.quality = quality | 0;
  35. }
  36. /**
  37. * 对渲染对象进行x、y轴同时设置模糊半径
  38. *
  39. * @member {number}
  40. * @name blur
  41. * @memberof JC.BlurFilter#
  42. */
  43. Object.defineProperty(BlurFilter.prototype, 'blur', {
  44. get: function() {
  45. return this.blurX;
  46. },
  47. set: function(blur) {
  48. this.blurX = this.blurY = blur;
  49. },
  50. });
  51. /* eslint max-len: "off" */
  52. const MUL_TABLE = [1, 171, 205, 293, 57, 373, 79, 137, 241, 27, 391, 357, 41, 19, 283, 265, 497, 469, 443, 421, 25, 191, 365, 349, 335, 161, 155, 149, 9, 278, 269, 261, 505, 245, 475, 231, 449, 437, 213, 415, 405, 395, 193, 377, 369, 361, 353, 345, 169, 331, 325, 319, 313, 307, 301, 37, 145, 285, 281, 69, 271, 267, 263, 259, 509, 501, 493, 243, 479, 118, 465, 459, 113, 446, 55, 435, 429, 423, 209, 413, 51, 403, 199, 393, 97, 3, 379, 375, 371, 367, 363, 359, 355, 351, 347, 43, 85, 337, 333, 165, 327, 323, 5, 317, 157, 311, 77, 305, 303, 75, 297, 294, 73, 289, 287, 71, 141, 279, 277, 275, 68, 135, 67, 133, 33, 262, 260, 129, 511, 507, 503, 499, 495, 491, 61, 121, 481, 477, 237, 235, 467, 232, 115, 457, 227, 451, 7, 445, 221, 439, 218, 433, 215, 427, 425, 211, 419, 417, 207, 411, 409, 203, 202, 401, 399, 396, 197, 49, 389, 387, 385, 383, 95, 189, 47, 187, 93, 185, 23, 183, 91, 181, 45, 179, 89, 177, 11, 175, 87, 173, 345, 343, 341, 339, 337, 21, 167, 83, 331, 329, 327, 163, 81, 323, 321, 319, 159, 79, 315, 313, 39, 155, 309, 307, 153, 305, 303, 151, 75, 299, 149, 37, 295, 147, 73, 291, 145, 289, 287, 143, 285, 71, 141, 281, 35, 279, 139, 69, 275, 137, 273, 17, 271, 135, 269, 267, 133, 265, 33, 263, 131, 261, 130, 259, 129, 257, 1];
  53. const SHG_TABLE = [0, 9, 10, 11, 9, 12, 10, 11, 12, 9, 13, 13, 10, 9, 13, 13, 14, 14, 14, 14, 10, 13, 14, 14, 14, 13, 13, 13, 9, 14, 14, 14, 15, 14, 15, 14, 15, 15, 14, 15, 15, 15, 14, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 12, 14, 15, 15, 13, 15, 15, 15, 15, 16, 16, 16, 15, 16, 14, 16, 16, 14, 16, 13, 16, 16, 16, 15, 16, 13, 16, 15, 16, 14, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 14, 16, 16, 15, 16, 16, 10, 16, 15, 16, 14, 16, 16, 14, 16, 16, 14, 16, 16, 14, 15, 16, 16, 16, 14, 15, 14, 15, 13, 16, 16, 15, 17, 17, 17, 17, 17, 17, 14, 15, 17, 17, 16, 16, 17, 16, 15, 17, 16, 17, 11, 17, 16, 17, 16, 17, 16, 17, 17, 16, 17, 17, 16, 17, 17, 16, 16, 17, 17, 17, 16, 14, 17, 17, 17, 17, 15, 16, 14, 16, 15, 16, 13, 16, 15, 16, 14, 16, 15, 16, 12, 16, 15, 16, 17, 17, 17, 17, 17, 13, 16, 15, 17, 17, 17, 16, 15, 17, 17, 17, 16, 15, 17, 17, 14, 16, 17, 17, 16, 17, 17, 16, 15, 17, 16, 14, 17, 16, 15, 17, 16, 17, 17, 16, 17, 15, 16, 17, 14, 17, 16, 15, 17, 16, 17, 13, 17, 16, 17, 17, 16, 17, 14, 17, 16, 17, 16, 17, 16, 17, 9];
  54. /* eslint-disable */
  55. BlurFilter.prototype.applyFilter = function(imageData) {
  56. var radiusX = this.blurX >> 1;
  57. if (isNaN(radiusX) || radiusX < 0) return false;
  58. var radiusY = this.blurY >> 1;
  59. if (isNaN(radiusY) || radiusY < 0) return false;
  60. if (radiusX == 0 && radiusY == 0) return false;
  61. var iterations = this.quality;
  62. if (isNaN(iterations) || iterations < 1) iterations = 1;
  63. iterations |= 0;
  64. if (iterations > 3) iterations = 3;
  65. if (iterations < 1) iterations = 1;
  66. var px = imageData.data;
  67. var x = 0,
  68. y = 0,
  69. i = 0,
  70. p = 0,
  71. yp = 0,
  72. yi = 0,
  73. yw = 0,
  74. r = 0,
  75. g = 0,
  76. b = 0,
  77. a = 0,
  78. pr = 0,
  79. pg = 0,
  80. pb = 0,
  81. pa = 0;
  82. var divx = (radiusX + radiusX + 1) | 0;
  83. var divy = (radiusY + radiusY + 1) | 0;
  84. var w = imageData.width | 0;
  85. var h = imageData.height | 0;
  86. var w1 = (w - 1) | 0;
  87. var h1 = (h - 1) | 0;
  88. var rxp1 = (radiusX + 1) | 0;
  89. var ryp1 = (radiusY + 1) | 0;
  90. var ssx = { r: 0, b: 0, g: 0, a: 0 };
  91. var sx = ssx;
  92. for (i = 1; i < divx; i++) {
  93. sx = sx.n = { r: 0, b: 0, g: 0, a: 0 };
  94. }
  95. sx.n = ssx;
  96. var ssy = { r: 0, b: 0, g: 0, a: 0 };
  97. var sy = ssy;
  98. for (i = 1; i < divy; i++) {
  99. sy = sy.n = { r: 0, b: 0, g: 0, a: 0 };
  100. }
  101. sy.n = ssy;
  102. var si = null;
  103. var mtx = MUL_TABLE[radiusX] | 0;
  104. var stx = SHG_TABLE[radiusX] | 0;
  105. var mty = MUL_TABLE[radiusY] | 0;
  106. var sty = SHG_TABLE[radiusY] | 0;
  107. while (iterations-- > 0) {
  108. yw = yi = 0;
  109. var ms = mtx;
  110. var ss = stx;
  111. for (y = h; --y > -1;) {
  112. r = rxp1 * (pr = px[(yi) | 0]);
  113. g = rxp1 * (pg = px[(yi + 1) | 0]);
  114. b = rxp1 * (pb = px[(yi + 2) | 0]);
  115. a = rxp1 * (pa = px[(yi + 3) | 0]);
  116. sx = ssx;
  117. for (i = rxp1; --i > -1;) {
  118. sx.r = pr;
  119. sx.g = pg;
  120. sx.b = pb;
  121. sx.a = pa;
  122. sx = sx.n;
  123. }
  124. for (i = 1; i < rxp1; i++) {
  125. p = (yi + ((w1 < i ? w1 : i) << 2)) | 0;
  126. r += (sx.r = px[p]);
  127. g += (sx.g = px[p + 1]);
  128. b += (sx.b = px[p + 2]);
  129. a += (sx.a = px[p + 3]);
  130. sx = sx.n;
  131. }
  132. si = ssx;
  133. for (x = 0; x < w; x++) {
  134. px[yi++] = (r * ms) >>> ss;
  135. px[yi++] = (g * ms) >>> ss;
  136. px[yi++] = (b * ms) >>> ss;
  137. px[yi++] = (a * ms) >>> ss;
  138. p = ((yw + ((p = x + radiusX + 1) < w1 ? p : w1)) << 2);
  139. r -= si.r - (si.r = px[p]);
  140. g -= si.g - (si.g = px[p + 1]);
  141. b -= si.b - (si.b = px[p + 2]);
  142. a -= si.a - (si.a = px[p + 3]);
  143. si = si.n;
  144. }
  145. yw += w;
  146. }
  147. ms = mty;
  148. ss = sty;
  149. for (x = 0; x < w; x++) {
  150. yi = (x << 2) | 0;
  151. r = (ryp1 * (pr = px[yi])) | 0;
  152. g = (ryp1 * (pg = px[(yi + 1) | 0])) | 0;
  153. b = (ryp1 * (pb = px[(yi + 2) | 0])) | 0;
  154. a = (ryp1 * (pa = px[(yi + 3) | 0])) | 0;
  155. sy = ssy;
  156. for (i = 0; i < ryp1; i++) {
  157. sy.r = pr;
  158. sy.g = pg;
  159. sy.b = pb;
  160. sy.a = pa;
  161. sy = sy.n;
  162. }
  163. yp = w;
  164. for (i = 1; i <= radiusY; i++) {
  165. yi = (yp + x) << 2;
  166. r += (sy.r = px[yi]);
  167. g += (sy.g = px[yi + 1]);
  168. b += (sy.b = px[yi + 2]);
  169. a += (sy.a = px[yi + 3]);
  170. sy = sy.n;
  171. if (i < h1) {
  172. yp += w;
  173. }
  174. }
  175. yi = x;
  176. si = ssy;
  177. if (iterations > 0) {
  178. for (y = 0; y < h; y++) {
  179. p = yi << 2;
  180. px[p + 3] = pa = (a * ms) >>> ss;
  181. if (pa > 0) {
  182. px[p] = ((r * ms) >>> ss);
  183. px[p + 1] = ((g * ms) >>> ss);
  184. px[p + 2] = ((b * ms) >>> ss);
  185. } else {
  186. px[p] = px[p + 1] = px[p + 2] = 0;
  187. }
  188. p = (x + (((p = y + ryp1) < h1 ? p : h1) * w)) << 2;
  189. r -= si.r - (si.r = px[p]);
  190. g -= si.g - (si.g = px[p + 1]);
  191. b -= si.b - (si.b = px[p + 2]);
  192. a -= si.a - (si.a = px[p + 3]);
  193. si = si.n;
  194. yi += w;
  195. }
  196. } else {
  197. for (y = 0; y < h; y++) {
  198. p = yi << 2;
  199. px[p + 3] = pa = (a * ms) >>> ss;
  200. if (pa > 0) {
  201. pa = 255 / pa;
  202. px[p] = ((r * ms) >>> ss) * pa;
  203. px[p + 1] = ((g * ms) >>> ss) * pa;
  204. px[p + 2] = ((b * ms) >>> ss) * pa;
  205. } else {
  206. px[p] = px[p + 1] = px[p + 2] = 0;
  207. }
  208. p = (x + (((p = y + ryp1) < h1 ? p : h1) * w)) << 2;
  209. r -= si.r - (si.r = px[p]);
  210. g -= si.g - (si.g = px[p + 1]);
  211. b -= si.b - (si.b = px[p + 2]);
  212. a -= si.a - (si.a = px[p + 3]);
  213. si = si.n;
  214. yi += w;
  215. }
  216. }
  217. }
  218. }
  219. return true;
  220. };
  221. export { BlurFilter };