UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 25.6 kB
{"version":3,"file":"Resize.min.mjs","sources":["../../../src/filters/Resize.ts"],"sourcesContent":["import { BaseFilter } from './BaseFilter';\nimport type {\n T2DPipelineState,\n TWebGLPipelineState,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport { classRegistry } from '../ClassRegistry';\nimport { createCanvasElement } from '../util/misc/dom';\nimport type { XY } from '../Point';\n\nexport type TResizeType = 'bilinear' | 'hermite' | 'sliceHack' | 'lanczos';\n\nexport type ResizeOwnProps = {\n resizeType: TResizeType;\n scaleX: number;\n scaleY: number;\n lanczosLobes: number;\n};\n\nexport const resizeDefaultValues: ResizeOwnProps = {\n resizeType: 'hermite',\n scaleX: 1,\n scaleY: 1,\n lanczosLobes: 3,\n};\n\ntype ResizeDuring2DResize = Resize & {\n rcpScaleX: number;\n rcpScaleY: number;\n};\n\ntype ResizeDuringWEBGLResize = Resize & {\n rcpScaleX: number;\n rcpScaleY: number;\n horizontal: boolean;\n width: number;\n height: number;\n taps: number[];\n tempScale: number;\n dH: number;\n dW: number;\n};\n\n/**\n * Resize image filter class\n * @example\n * const filter = new Resize();\n * object.filters.push(filter);\n * object.applyFilters(canvas.renderAll.bind(canvas));\n */\nexport class Resize extends BaseFilter<'Resize', ResizeOwnProps> {\n /**\n * Resize type\n * for webgl resizeType is just lanczos, for canvas2d can be:\n * bilinear, hermite, sliceHack, lanczos.\n * @default\n */\n declare resizeType: ResizeOwnProps['resizeType'];\n\n /**\n * Scale factor for resizing, x axis\n * @param {Number} scaleX\n * @default\n */\n declare scaleX: ResizeOwnProps['scaleX'];\n\n /**\n * Scale factor for resizing, y axis\n * @param {Number} scaleY\n * @default\n */\n declare scaleY: ResizeOwnProps['scaleY'];\n\n /**\n * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n * @param {Number} lanczosLobes\n * @default\n */\n declare lanczosLobes: ResizeOwnProps['lanczosLobes'];\n\n static type = 'Resize';\n\n static defaults = resizeDefaultValues;\n\n static uniformLocations = ['uDelta', 'uTaps'];\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 this: ResizeDuringWEBGLResize,\n gl: WebGLRenderingContext,\n uniformLocations: TWebGLUniformLocationMap,\n ) {\n gl.uniform2fv(\n uniformLocations.uDelta,\n this.horizontal ? [1 / this.width, 0] : [0, 1 / this.height],\n );\n gl.uniform1fv(uniformLocations.uTaps, this.taps);\n }\n\n getFilterWindow(this: ResizeDuringWEBGLResize) {\n const scale = this.tempScale;\n return Math.ceil(this.lanczosLobes / scale);\n }\n\n getCacheKey(this: ResizeDuringWEBGLResize): string {\n const filterWindow = this.getFilterWindow();\n return `${this.type}_${filterWindow}`;\n }\n\n getFragmentSource(this: ResizeDuringWEBGLResize): string {\n const filterWindow = this.getFilterWindow();\n return this.generateShader(filterWindow);\n }\n\n getTaps(this: ResizeDuringWEBGLResize) {\n const lobeFunction = this.lanczosCreate(this.lanczosLobes),\n scale = this.tempScale,\n filterWindow = this.getFilterWindow(),\n taps = new Array(filterWindow);\n for (let i = 1; i <= filterWindow; i++) {\n taps[i - 1] = lobeFunction(i * scale);\n }\n return taps;\n }\n\n /**\n * Generate vertex and shader sources from the necessary steps numbers\n * @param {Number} filterWindow\n */\n generateShader(filterWindow: number) {\n const offsets = new Array(filterWindow);\n for (let i = 1; i <= filterWindow; i++) {\n offsets[i - 1] = `${i}.0 * uDelta`;\n }\n return `\n precision highp float;\n uniform sampler2D uTexture;\n uniform vec2 uDelta;\n varying vec2 vTexCoord;\n uniform float uTaps[${filterWindow}];\n void main() {\n vec4 color = texture2D(uTexture, vTexCoord);\n float sum = 1.0;\n ${offsets\n .map(\n (offset, i) => `\n color += texture2D(uTexture, vTexCoord + ${offset}) * uTaps[${i}] + texture2D(uTexture, vTexCoord - ${offset}) * uTaps[${i}];\n sum += 2.0 * uTaps[${i}];\n `,\n )\n .join('\\n')}\n gl_FragColor = color / sum;\n }\n `;\n }\n\n applyToForWebgl(this: ResizeDuringWEBGLResize, options: TWebGLPipelineState) {\n options.passes++;\n this.width = options.sourceWidth;\n this.horizontal = true;\n this.dW = Math.round(this.width * this.scaleX);\n this.dH = options.sourceHeight;\n this.tempScale = this.dW / this.width;\n this.taps = this.getTaps();\n options.destinationWidth = this.dW;\n super.applyTo(options);\n options.sourceWidth = options.destinationWidth;\n\n this.height = options.sourceHeight;\n this.horizontal = false;\n this.dH = Math.round(this.height * this.scaleY);\n this.tempScale = this.dH / this.height;\n this.taps = this.getTaps();\n options.destinationHeight = this.dH;\n super.applyTo(options);\n options.sourceHeight = options.destinationHeight;\n }\n\n /**\n * Apply the resize filter to the image\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\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 applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n if (isWebGLPipelineState(options)) {\n (this as unknown as ResizeDuringWEBGLResize).applyToForWebgl(options);\n } else {\n (this as unknown as ResizeDuring2DResize).applyTo2d(options);\n }\n }\n\n isNeutralState() {\n return this.scaleX === 1 && this.scaleY === 1;\n }\n\n lanczosCreate(lobes: number) {\n return (x: number) => {\n if (x >= lobes || x <= -lobes) {\n return 0.0;\n }\n if (x < 1.1920929e-7 && x > -1.1920929e-7) {\n return 1.0;\n }\n x *= Math.PI;\n const xx = x / lobes;\n return ((Math.sin(x) / x) * Math.sin(xx)) / xx;\n };\n }\n\n applyTo2d(this: ResizeDuring2DResize, options: T2DPipelineState) {\n const imageData = options.imageData,\n scaleX = this.scaleX,\n scaleY = this.scaleY;\n\n this.rcpScaleX = 1 / scaleX;\n this.rcpScaleY = 1 / scaleY;\n\n const oW = imageData.width;\n const oH = imageData.height;\n const dW = Math.round(oW * scaleX);\n const dH = Math.round(oH * scaleY);\n let newData: ImageData;\n\n if (this.resizeType === 'sliceHack') {\n newData = this.sliceByTwo(options, oW, oH, dW, dH);\n } else if (this.resizeType === 'hermite') {\n newData = this.hermiteFastResize(options, oW, oH, dW, dH);\n } else if (this.resizeType === 'bilinear') {\n newData = this.bilinearFiltering(options, oW, oH, dW, dH);\n } else if (this.resizeType === 'lanczos') {\n newData = this.lanczosResize(options, oW, oH, dW, dH);\n } else {\n // this should never trigger, is here just for safety net.\n newData = new ImageData(dW, dH);\n }\n options.imageData = newData;\n }\n\n /**\n * Filter sliceByTwo\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n sliceByTwo(\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ) {\n const imageData = options.imageData;\n const mult = 0.5;\n let doneW = false;\n let doneH = false;\n let stepW = oW * mult;\n let stepH = oH * mult;\n const resources = options.filterBackend.resources;\n let sX = 0;\n let sY = 0;\n const dX = oW;\n let dY = 0;\n if (!resources.sliceByTwo) {\n resources.sliceByTwo = createCanvasElement();\n }\n const tmpCanvas = resources.sliceByTwo;\n if (tmpCanvas.width < oW * 1.5 || tmpCanvas.height < oH) {\n tmpCanvas.width = oW * 1.5;\n tmpCanvas.height = oH;\n }\n const ctx = tmpCanvas.getContext('2d')!;\n ctx.clearRect(0, 0, oW * 1.5, oH);\n ctx.putImageData(imageData, 0, 0);\n\n dW = Math.floor(dW);\n dH = Math.floor(dH);\n\n while (!doneW || !doneH) {\n oW = stepW;\n oH = stepH;\n if (dW < Math.floor(stepW * mult)) {\n stepW = Math.floor(stepW * mult);\n } else {\n stepW = dW;\n doneW = true;\n }\n if (dH < Math.floor(stepH * mult)) {\n stepH = Math.floor(stepH * mult);\n } else {\n stepH = dH;\n doneH = true;\n }\n ctx.drawImage(tmpCanvas, sX, sY, oW, oH, dX, dY, stepW, stepH);\n sX = dX;\n sY = dY;\n dY += stepH;\n }\n return ctx.getImageData(sX, sY, dW, dH);\n }\n\n /**\n * Filter lanczosResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n lanczosResize(\n this: ResizeDuring2DResize,\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ): ImageData {\n function process(u: number): ImageData {\n let v, i, weight, idx, a, red, green, blue, alpha, fX, fY;\n center.x = (u + 0.5) * ratioX;\n icenter.x = Math.floor(center.x);\n for (v = 0; v < dH; v++) {\n center.y = (v + 0.5) * ratioY;\n icenter.y = Math.floor(center.y);\n a = 0;\n red = 0;\n green = 0;\n blue = 0;\n alpha = 0;\n for (i = icenter.x - range2X; i <= icenter.x + range2X; i++) {\n if (i < 0 || i >= oW) {\n continue;\n }\n fX = Math.floor(1000 * Math.abs(i - center.x));\n if (!cacheLanc[fX]) {\n cacheLanc[fX] = {};\n }\n for (let j = icenter.y - range2Y; j <= icenter.y + range2Y; j++) {\n if (j < 0 || j >= oH) {\n continue;\n }\n fY = Math.floor(1000 * Math.abs(j - center.y));\n if (!cacheLanc[fX][fY]) {\n cacheLanc[fX][fY] = lanczos(\n Math.sqrt(\n Math.pow(fX * rcpRatioX, 2) + Math.pow(fY * rcpRatioY, 2),\n ) / 1000,\n );\n }\n weight = cacheLanc[fX][fY];\n if (weight > 0) {\n idx = (j * oW + i) * 4;\n a += weight;\n red += weight * srcData[idx];\n green += weight * srcData[idx + 1];\n blue += weight * srcData[idx + 2];\n alpha += weight * srcData[idx + 3];\n }\n }\n }\n idx = (v * dW + u) * 4;\n destData[idx] = red / a;\n destData[idx + 1] = green / a;\n destData[idx + 2] = blue / a;\n destData[idx + 3] = alpha / a;\n }\n\n if (++u < dW) {\n return process(u);\n } else {\n return destImg;\n }\n }\n\n const srcData = options.imageData.data,\n destImg = options.ctx.createImageData(dW, dH),\n destData = destImg.data,\n lanczos = this.lanczosCreate(this.lanczosLobes),\n ratioX = this.rcpScaleX,\n ratioY = this.rcpScaleY,\n rcpRatioX = 2 / this.rcpScaleX,\n rcpRatioY = 2 / this.rcpScaleY,\n range2X = Math.ceil((ratioX * this.lanczosLobes) / 2),\n range2Y = Math.ceil((ratioY * this.lanczosLobes) / 2),\n cacheLanc: Record<number, Record<number, number>> = {},\n center: XY = { x: 0, y: 0 },\n icenter: XY = { x: 0, y: 0 };\n\n return process(0);\n }\n\n /**\n * bilinearFiltering\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n bilinearFiltering(\n this: ResizeDuring2DResize,\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ) {\n let a;\n let b;\n let c;\n let d;\n let x;\n let y;\n let i;\n let j;\n let xDiff;\n let yDiff;\n let chnl;\n let color;\n let offset = 0;\n let origPix;\n const ratioX = this.rcpScaleX;\n const ratioY = this.rcpScaleY;\n const w4 = 4 * (oW - 1);\n const img = options.imageData;\n const pixels = img.data;\n const destImage = options.ctx.createImageData(dW, dH);\n const destPixels = destImage.data;\n for (i = 0; i < dH; i++) {\n for (j = 0; j < dW; j++) {\n x = Math.floor(ratioX * j);\n y = Math.floor(ratioY * i);\n xDiff = ratioX * j - x;\n yDiff = ratioY * i - y;\n origPix = 4 * (y * oW + x);\n\n for (chnl = 0; chnl < 4; chnl++) {\n a = pixels[origPix + chnl];\n b = pixels[origPix + 4 + chnl];\n c = pixels[origPix + w4 + chnl];\n d = pixels[origPix + w4 + 4 + chnl];\n color =\n a * (1 - xDiff) * (1 - yDiff) +\n b * xDiff * (1 - yDiff) +\n c * yDiff * (1 - xDiff) +\n d * xDiff * yDiff;\n destPixels[offset++] = color;\n }\n }\n }\n return destImage;\n }\n\n /**\n * hermiteFastResize\n * @param {Object} canvasEl Canvas element to apply filter to\n * @param {Number} oW Original Width\n * @param {Number} oH Original Height\n * @param {Number} dW Destination Width\n * @param {Number} dH Destination Height\n * @returns {ImageData}\n */\n hermiteFastResize(\n this: ResizeDuring2DResize,\n options: T2DPipelineState,\n oW: number,\n oH: number,\n dW: number,\n dH: number,\n ) {\n const ratioW = this.rcpScaleX,\n ratioH = this.rcpScaleY,\n ratioWHalf = Math.ceil(ratioW / 2),\n ratioHHalf = Math.ceil(ratioH / 2),\n img = options.imageData,\n data = img.data,\n img2 = options.ctx.createImageData(dW, dH),\n data2 = img2.data;\n for (let j = 0; j < dH; j++) {\n for (let i = 0; i < dW; i++) {\n const x2 = (i + j * dW) * 4;\n let weight = 0;\n let weights = 0;\n let weightsAlpha = 0;\n let gxR = 0;\n let gxG = 0;\n let gxB = 0;\n let gxA = 0;\n const centerY = (j + 0.5) * ratioH;\n for (let yy = Math.floor(j * ratioH); yy < (j + 1) * ratioH; yy++) {\n const dy = Math.abs(centerY - (yy + 0.5)) / ratioHHalf,\n centerX = (i + 0.5) * ratioW,\n w0 = dy * dy;\n for (let xx = Math.floor(i * ratioW); xx < (i + 1) * ratioW; xx++) {\n let dx = Math.abs(centerX - (xx + 0.5)) / ratioWHalf;\n const w = Math.sqrt(w0 + dx * dx);\n /* eslint-disable max-depth */\n if (w > 1 && w < -1) {\n continue;\n }\n //hermite filter\n weight = 2 * w * w * w - 3 * w * w + 1;\n if (weight > 0) {\n dx = 4 * (xx + yy * oW);\n //alpha\n gxA += weight * data[dx + 3];\n weightsAlpha += weight;\n //colors\n if (data[dx + 3] < 255) {\n weight = (weight * data[dx + 3]) / 250;\n }\n gxR += weight * data[dx];\n gxG += weight * data[dx + 1];\n gxB += weight * data[dx + 2];\n weights += weight;\n }\n /* eslint-enable max-depth */\n }\n }\n data2[x2] = gxR / weights;\n data2[x2 + 1] = gxG / weights;\n data2[x2 + 2] = gxB / weights;\n data2[x2 + 3] = gxA / weightsAlpha;\n }\n }\n return img2;\n }\n}\n\nclassRegistry.setClass(Resize);\n"],"names":["resizeDefaultValues","resizeType","scaleX","scaleY","lanczosLobes","Resize","BaseFilter","sendUniformData","gl","uniformLocations","uniform2fv","uDelta","this","horizontal","width","height","uniform1fv","uTaps","taps","getFilterWindow","scale","tempScale","Math","ceil","getCacheKey","filterWindow","concat","type","getFragmentSource","generateShader","getTaps","lobeFunction","lanczosCreate","Array","i","offsets","map","offset","join","applyToForWebgl","options","passes","sourceWidth","dW","round","dH","sourceHeight","destinationWidth","super","applyTo","destinationHeight","isWebGLPipelineState","applyTo2d","isNeutralState","lobes","x","xx","PI","sin","imageData","rcpScaleX","rcpScaleY","oW","oH","newData","sliceByTwo","hermiteFastResize","bilinearFiltering","lanczosResize","ImageData","mult","doneW","doneH","stepW","stepH","resources","filterBackend","sX","sY","dX","dY","createCanvasElement","tmpCanvas","ctx","getContext","clearRect","putImageData","floor","drawImage","getImageData","srcData","data","destImg","createImageData","destData","lanczos","ratioX","ratioY","rcpRatioX","rcpRatioY","range2X","range2Y","cacheLanc","center","y","icenter","process","u","v","weight","idx","a","red","green","blue","alpha","fX","fY","abs","j","sqrt","pow","b","c","d","xDiff","yDiff","chnl","color","origPix","w4","pixels","destImage","destPixels","ratioW","ratioH","ratioWHalf","ratioHHalf","img2","data2","x2","weights","weightsAlpha","gxR","gxG","gxB","gxA","centerY","yy","dy","centerX","w0","dx","w","_defineProperty","classRegistry","setClass"],"mappings":"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"}