{"version":3,"file":"Blur.min.mjs","sources":["../../../src/filters/Blur.ts"],"sourcesContent":["import { createCanvasElement } from '../util/misc/dom';\nimport { BaseFilter } from './BaseFilter';\nimport type {\n  TWebGLPipelineState,\n  T2DPipelineState,\n  TWebGLUniformLocationMap,\n} from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource } from './shaders/blur';\n\ntype BlurOwnProps = {\n  blur: number;\n};\n\nexport const blurDefaultValues: BlurOwnProps = {\n  blur: 0,\n};\n\n/**\n * Blur filter class\n * @example\n * const filter = new Blur({\n *   blur: 0.5\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class Blur extends BaseFilter<'Blur', BlurOwnProps> {\n  /**\n   * blur value, in percentage of image dimensions.\n   * specific to keep the image blur constant at different resolutions\n   * range between 0 and 1.\n   * @type Number\n   * @default\n   */\n  declare blur: BlurOwnProps['blur'];\n\n  declare horizontal: boolean;\n  declare aspectRatio: number;\n\n  static type = 'Blur';\n\n  static defaults = blurDefaultValues;\n\n  static uniformLocations = ['uDelta'];\n\n  getFragmentSource(): string {\n    return fragmentSource;\n  }\n\n  applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n    if (isWebGLPipelineState(options)) {\n      // this aspectRatio is used to give the same blur to vertical and horizontal\n      this.aspectRatio = options.sourceWidth / options.sourceHeight;\n      options.passes++;\n      this._setupFrameBuffer(options);\n      this.horizontal = true;\n      this.applyToWebGL(options);\n      this._swapTextures(options);\n      this._setupFrameBuffer(options);\n      this.horizontal = false;\n      this.applyToWebGL(options);\n      this._swapTextures(options);\n    } else {\n      this.applyTo2d(options);\n    }\n  }\n\n  applyTo2d(options: T2DPipelineState) {\n    options.imageData = this.simpleBlur(options);\n  }\n\n  simpleBlur({\n    ctx,\n    imageData,\n    filterBackend: { resources },\n  }: T2DPipelineState) {\n    const { width, height } = imageData;\n    if (!resources.blurLayer1) {\n      resources.blurLayer1 = createCanvasElement();\n      resources.blurLayer2 = createCanvasElement();\n    }\n    const canvas1 = resources.blurLayer1!;\n    const canvas2 = resources.blurLayer2!;\n    if (canvas1.width !== width || canvas1.height !== height) {\n      canvas2.width = canvas1.width = width;\n      canvas2.height = canvas1.height = height;\n    }\n    const ctx1 = canvas1.getContext('2d')!,\n      ctx2 = canvas2.getContext('2d')!,\n      nSamples = 15,\n      blur = this.blur * 0.06 * 0.5;\n    let random, percent, j, i;\n\n    // load first canvas\n    ctx1.putImageData(imageData, 0, 0);\n    ctx2.clearRect(0, 0, width, height);\n\n    for (i = -nSamples; i <= nSamples; i++) {\n      random = (Math.random() - 0.5) / 4;\n      percent = i / nSamples;\n      j = blur * percent * width + random;\n      ctx2.globalAlpha = 1 - Math.abs(percent);\n      ctx2.drawImage(canvas1, j, random);\n      ctx1.drawImage(canvas2, 0, 0);\n      ctx2.globalAlpha = 1;\n      ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n    }\n    for (i = -nSamples; i <= nSamples; i++) {\n      random = (Math.random() - 0.5) / 4;\n      percent = i / nSamples;\n      j = blur * percent * height + random;\n      ctx2.globalAlpha = 1 - Math.abs(percent);\n      ctx2.drawImage(canvas1, random, j);\n      ctx1.drawImage(canvas2, 0, 0);\n      ctx2.globalAlpha = 1;\n      ctx2.clearRect(0, 0, canvas2.width, canvas2.height);\n    }\n    ctx.drawImage(canvas1, 0, 0);\n    const newImageData = ctx.getImageData(0, 0, canvas1.width, canvas1.height);\n    ctx1.globalAlpha = 1;\n    ctx1.clearRect(0, 0, canvas1.width, canvas1.height);\n    return newImageData;\n  }\n\n  /**\n   * Send data from this filter to its shader program's uniforms.\n   *\n   * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader.\n   * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects\n   */\n  sendUniformData(\n    gl: WebGLRenderingContext,\n    uniformLocations: TWebGLUniformLocationMap,\n  ) {\n    const delta = this.chooseRightDelta();\n    gl.uniform2fv(uniformLocations.uDelta, delta);\n  }\n\n  isNeutralState() {\n    return this.blur === 0;\n  }\n\n  /**\n   * choose right value of image percentage to blur with\n   * @returns {Array} a numeric array with delta values\n   */\n  chooseRightDelta() {\n    let blurScale = 1;\n    const delta = [0, 0];\n    if (this.horizontal) {\n      if (this.aspectRatio > 1) {\n        // image is wide, i want to shrink radius horizontal\n        blurScale = 1 / this.aspectRatio;\n      }\n    } else {\n      if (this.aspectRatio < 1) {\n        // image is tall, i want to shrink radius vertical\n        blurScale = this.aspectRatio;\n      }\n    }\n    const blur = blurScale * this.blur * 0.12;\n    if (this.horizontal) {\n      delta[0] = blur;\n    } else {\n      delta[1] = blur;\n    }\n    return delta;\n  }\n}\n\nclassRegistry.setClass(Blur);\n"],"names":["blurDefaultValues","blur","Blur","BaseFilter","getFragmentSource","fragmentSource","applyTo","options","isWebGLPipelineState","this","aspectRatio","sourceWidth","sourceHeight","passes","_setupFrameBuffer","horizontal","applyToWebGL","_swapTextures","applyTo2d","imageData","simpleBlur","_ref","ctx","filterBackend","resources","width","height","blurLayer1","createCanvasElement","blurLayer2","canvas1","canvas2","ctx1","getContext","ctx2","nSamples","random","percent","j","i","putImageData","clearRect","Math","globalAlpha","abs","drawImage","newImageData","getImageData","sendUniformData","gl","uniformLocations","delta","chooseRightDelta","uniform2fv","uDelta","isNeutralState","blurScale","_defineProperty","classRegistry","setClass"],"mappings":"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"}