fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 12.8 kB
Source Map (JSON)
{"version":3,"file":"Blur.mjs","sources":["../../../src/filters/Blur.ts"],"sourcesContent":["import { 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({ imageData: { data, width, height } }: T2DPipelineState) {\n // this code mimic the shader for output consistency\n // it samples 31 pixels across the image over a distance that depends from the blur value.\n this.aspectRatio = width / height;\n this.horizontal = true;\n let blurValue = this.getBlurValue() * width;\n const imageData = new Uint8ClampedArray(data);\n const samples = 15;\n const bytesInRow = 4 * width;\n for (let i = 0; i < data.length; i += 4) {\n let r = 0.0,\n g = 0.0,\n b = 0.0,\n a = 0.0,\n totalA = 0;\n const minIRow = i - (i % bytesInRow);\n const maxIRow = minIRow + bytesInRow;\n // for now let's keep noise out of the way\n // let pixelOffset = 0;\n // const offset = Math.random() * 3;\n // if (offset > 2) {\n // pixelOffset = 4;\n // } else if (offset < 1) {\n // pixelOffset = -4;\n // }\n for (let j = -samples + 1; j < samples; j++) {\n const percent = j / samples;\n const distance = Math.floor(blurValue * percent) * 4;\n const weight = 1 - Math.abs(percent);\n let sampledPixel = i + distance; // + pixelOffset;\n // try to implement edge mirroring\n if (sampledPixel < minIRow) {\n sampledPixel = minIRow;\n } else if (sampledPixel > maxIRow) {\n sampledPixel = maxIRow;\n }\n const localAlpha = data[sampledPixel + 3] * weight;\n r += data[sampledPixel] * localAlpha;\n g += data[sampledPixel + 1] * localAlpha;\n b += data[sampledPixel + 2] * localAlpha;\n a += localAlpha;\n totalA += weight;\n }\n imageData[i] = r / a;\n imageData[i + 1] = g / a;\n imageData[i + 2] = b / a;\n imageData[i + 3] = a / totalA;\n }\n this.horizontal = false;\n blurValue = this.getBlurValue() * height;\n for (let i = 0; i < imageData.length; i += 4) {\n let r = 0.0,\n g = 0.0,\n b = 0.0,\n a = 0.0,\n totalA = 0;\n const minIRow = i % bytesInRow;\n const maxIRow = imageData.length - bytesInRow + minIRow;\n // for now let's keep noise out of the way\n // let pixelOffset = 0;\n // const offset = Math.random() * 3;\n // if (offset > 2) {\n // pixelOffset = bytesInRow;\n // } else if (offset < 1) {\n // pixelOffset = -bytesInRow;\n // }\n for (let j = -samples + 1; j < samples; j++) {\n const percent = j / samples;\n const distance = Math.floor(blurValue * percent) * bytesInRow;\n const weight = 1 - Math.abs(percent);\n let sampledPixel = i + distance; // + pixelOffset;\n // try to implement edge mirroring\n if (sampledPixel < minIRow) {\n sampledPixel = minIRow;\n } else if (sampledPixel > maxIRow) {\n sampledPixel = maxIRow;\n }\n const localAlpha = imageData[sampledPixel + 3] * weight;\n r += imageData[sampledPixel] * localAlpha;\n g += imageData[sampledPixel + 1] * localAlpha;\n b += imageData[sampledPixel + 2] * localAlpha;\n a += localAlpha;\n totalA += weight;\n }\n data[i] = r / a;\n data[i + 1] = g / a;\n data[i + 2] = b / a;\n data[i + 3] = a / totalA;\n }\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 getBlurValue(): number {\n let blurScale = 1;\n const { horizontal, aspectRatio } = this;\n if (horizontal) {\n if (aspectRatio > 1) {\n // image is wide, i want to shrink radius horizontal\n blurScale = 1 / aspectRatio;\n }\n } else {\n if (aspectRatio < 1) {\n // image is tall, i want to shrink radius vertical\n blurScale = aspectRatio;\n }\n }\n return blurScale * this.blur * 0.12;\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 const blur = this.getBlurValue();\n return this.horizontal ? [blur, 0] : [0, blur];\n }\n}\n\nclassRegistry.setClass(Blur);\n"],"names":["blurDefaultValues","blur","Blur","BaseFilter","getFragmentSource","fragmentSource","applyTo","options","isWebGLPipelineState","aspectRatio","sourceWidth","sourceHeight","passes","_setupFrameBuffer","horizontal","applyToWebGL","_swapTextures","applyTo2d","_ref","imageData","data","width","height","blurValue","getBlurValue","Uint8ClampedArray","samples","bytesInRow","i","length","r","g","b","a","totalA","minIRow","maxIRow","j","percent","distance","Math","floor","weight","abs","sampledPixel","localAlpha","sendUniformData","gl","uniformLocations","delta","chooseRightDelta","uniform2fv","uDelta","isNeutralState","blurScale","_defineProperty","classRegistry","setClass"],"mappings":"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"}