fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 9.92 kB
Source Map (JSON)
{"version":3,"file":"BlendImage.min.mjs","sources":["../../../src/filters/BlendImage.ts"],"sourcesContent":["import { FabricImage } from '../shapes/Image';\nimport { createCanvasElement } from '../util/misc/dom';\nimport { BaseFilter } from './BaseFilter';\nimport type {\n T2DPipelineState,\n TWebGLPipelineState,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport type { WebGLFilterBackend } from './WebGLFilterBackend';\nimport { classRegistry } from '../ClassRegistry';\nimport { fragmentSource, vertexSource } from './shaders/blendImage';\n\nexport type TBlendImageMode = 'multiply' | 'mask';\n\ntype BlendImageOwnProps = {\n mode: TBlendImageMode;\n alpha: number;\n};\n\nexport const blendImageDefaultValues: BlendImageOwnProps = {\n mode: 'multiply',\n alpha: 1,\n};\n\n/**\n * Image Blend filter class\n * @example\n * const filter = new filters.BlendColor({\n * color: '#000',\n * mode: 'multiply'\n * });\n *\n * const filter = new BlendImage({\n * image: fabricImageObject,\n * mode: 'multiply'\n * });\n * object.filters.push(filter);\n * object.applyFilters();\n * canvas.renderAll();\n */\nexport class BlendImage extends BaseFilter<'BlendImage', BlendImageOwnProps> {\n /**\n * Image to make the blend operation with.\n **/\n declare image: FabricImage;\n\n /**\n * Blend mode for the filter: either 'multiply' or 'mask'. 'multiply' will\n * multiply the values of each channel (R, G, B, and A) of the filter image by\n * their corresponding values in the base image. 'mask' will only look at the\n * alpha channel of the filter image, and apply those values to the base\n * image's alpha channel.\n * @type String\n * @default\n **/\n declare mode: BlendImageOwnProps['mode'];\n\n /**\n * alpha value. represent the strength of the blend image operation.\n * not implemented.\n **/\n declare alpha: BlendImageOwnProps['alpha'];\n\n static type = 'BlendImage';\n\n static defaults = blendImageDefaultValues;\n\n static uniformLocations = ['uTransformMatrix', 'uImage'];\n\n getCacheKey() {\n return `${this.type}_${this.mode}`;\n }\n\n getFragmentSource(): string {\n return fragmentSource[this.mode];\n }\n\n getVertexSource(): string {\n return vertexSource;\n }\n\n applyToWebGL(options: TWebGLPipelineState) {\n const gl = options.context,\n texture = this.createTexture(options.filterBackend, this.image);\n this.bindAdditionalTexture(gl, texture!, gl.TEXTURE1);\n super.applyToWebGL(options);\n this.unbindAdditionalTexture(gl, gl.TEXTURE1);\n }\n\n createTexture(backend: WebGLFilterBackend, image: FabricImage) {\n return backend.getCachedTexture(image.cacheKey, image.getElement());\n }\n\n /**\n * Calculate a transformMatrix to adapt the image to blend over\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n calculateMatrix() {\n const image = this.image,\n { width, height } = image.getElement();\n return [\n 1 / image.scaleX,\n 0,\n 0,\n 0,\n 1 / image.scaleY,\n 0,\n -image.left / width,\n -image.top / height,\n 1,\n ];\n }\n\n /**\n * Apply the Blend operation to a Uint8ClampedArray representing the pixels of an image.\n *\n * @param {Object} options\n * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered.\n */\n applyTo2d({\n imageData: { data, width, height },\n filterBackend: { resources },\n }: T2DPipelineState) {\n const image = this.image;\n if (!resources.blendImage) {\n resources.blendImage = createCanvasElement();\n }\n const canvas1 = resources.blendImage;\n const context = canvas1.getContext('2d')!;\n if (canvas1.width !== width || canvas1.height !== height) {\n canvas1.width = width;\n canvas1.height = height;\n } else {\n context.clearRect(0, 0, width, height);\n }\n context.setTransform(\n image.scaleX,\n 0,\n 0,\n image.scaleY,\n image.left,\n image.top,\n );\n context.drawImage(image.getElement(), 0, 0, width, height);\n const blendData = context.getImageData(0, 0, width, height).data;\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const a = data[i + 3];\n\n const tr = blendData[i];\n const tg = blendData[i + 1];\n const tb = blendData[i + 2];\n const ta = blendData[i + 3];\n\n switch (this.mode) {\n case 'multiply':\n data[i] = (r * tr) / 255;\n data[i + 1] = (g * tg) / 255;\n data[i + 2] = (b * tb) / 255;\n data[i + 3] = (a * ta) / 255;\n break;\n case 'mask':\n data[i + 3] = ta;\n break;\n }\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 matrix = this.calculateMatrix();\n gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.\n gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);\n }\n\n /**\n * Returns object representation of an instance\n * TODO: Handle the possibility of missing image better.\n * As of now a BlendImage filter without image can't be used with fromObject\n * @return {Object} Object representation of an instance\n */\n toObject(): {\n type: 'BlendImage';\n image: ReturnType<FabricImage['toObject']>;\n } & BlendImageOwnProps {\n return {\n ...super.toObject(),\n image: this.image && this.image.toObject(),\n };\n }\n\n /**\n * Create filter instance from an object representation\n * @static\n * @param {object} object Object to create an instance from\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting image loading, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<BlendImage>}\n */\n static async fromObject(\n { type, image, ...filterOptions }: Record<string, any>,\n options: { signal: AbortSignal },\n ): Promise<BaseFilter<'BlendImage', BlendImageOwnProps>> {\n return FabricImage.fromObject(image, options).then(\n (enlivedImage) =>\n new this({ ...filterOptions, image: enlivedImage }) as BlendImage,\n );\n }\n}\n\nclassRegistry.setClass(BlendImage);\n"],"names":["blendImageDefaultValues","mode","alpha","BlendImage","BaseFilter","getCacheKey","concat","this","type","getFragmentSource","fragmentSource","getVertexSource","vertexSource","applyToWebGL","options","gl","context","texture","createTexture","filterBackend","image","bindAdditionalTexture","TEXTURE1","super","unbindAdditionalTexture","backend","getCachedTexture","cacheKey","getElement","calculateMatrix","width","height","scaleX","scaleY","left","top","applyTo2d","_ref","imageData","data","resources","blendImage","createCanvasElement","canvas1","getContext","clearRect","setTransform","drawImage","blendData","getImageData","i","length","r","g","b","a","tr","tg","tb","ta","sendUniformData","uniformLocations","matrix","uniform1i","uImage","uniformMatrix3fv","uTransformMatrix","toObject","_objectSpread","fromObject","_ref2","filterOptions","_objectWithoutProperties","_excluded","FabricImage","then","enlivedImage","_defineProperty","classRegistry","setClass"],"mappings":"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"}