{"version":3,"file":"Resize.mjs","names":[],"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 type ResizeSerializedProps = ResizeOwnProps;\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   */\n  declare resizeType: ResizeOwnProps['resizeType'];\n\n  /**\n   * Scale factor for resizing, x axis\n   * @param {Number} scaleX\n   */\n  declare scaleX: ResizeOwnProps['scaleX'];\n\n  /**\n   * Scale factor for resizing, y axis\n   * @param {Number} scaleY\n   */\n  declare scaleY: ResizeOwnProps['scaleY'];\n\n  /**\n   * LanczosLobes parameter for lanczos filter, valid for resizeType lanczos\n   * @param {Number} lanczosLobes\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\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          }\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"],"mappings":"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"}