diff --git a/CHANGELOG.md b/CHANGELOG.md index 4caf4a9..70f1145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - 修复懒加载在多次点击出现卡死的问题 - 支持多种组合变换 - 提供清理缓存能力 +- ImageKnife下采样优化 ## 2.2.0-rc.2 - ImageKnife支持下采样 diff --git a/library/index.ets b/library/index.ets index a4ed680..1d8e1a5 100644 --- a/library/index.ets +++ b/library/index.ets @@ -135,4 +135,12 @@ export { LogUtil } from './src/main/ets/components/imageknife/utils/LogUtil' /*下采样*/ export {Downsampler} from './src/main/ets/components/imageknife/downsampling/Downsampler' -export {DownsampleNone as sampleNone, FitCenter as fitter} from './src/main/ets/components/imageknife/downsampling/DownsampleStartegy' \ No newline at end of file +export { + DownsampleNone as sampleNone, + FitCenter as fitter, + CenterOutside, + Atleast, + AtMost, + CenterInside as Center_Inside + +} from './src/main/ets/components/imageknife/downsampling/DownsampleStartegy' \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/downsampling/BaseDownsampling.ets b/library/src/main/ets/components/imageknife/downsampling/BaseDownsampling.ets index 62a04a8..43ec034 100644 --- a/library/src/main/ets/components/imageknife/downsampling/BaseDownsampling.ets +++ b/library/src/main/ets/components/imageknife/downsampling/BaseDownsampling.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { lang } from '@kit.ArkTS'; type ISendable = lang.ISendable; diff --git a/library/src/main/ets/components/imageknife/downsampling/DownsampleStartegy.ets b/library/src/main/ets/components/imageknife/downsampling/DownsampleStartegy.ets index 9a756ed..8223d1e 100644 --- a/library/src/main/ets/components/imageknife/downsampling/DownsampleStartegy.ets +++ b/library/src/main/ets/components/imageknife/downsampling/DownsampleStartegy.ets @@ -12,138 +12,152 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BaseDownsampling } from './BaseDownsampling' -@Sendable -export class CenterInside { - getName() { - return "CenterInside" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - return Math.min(1, this.getScale(sourceWidth, sourceHeight, requestWidth, requestHeight)) - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - //下采样因子 - return 1 - } - - getScale(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - let widthPercentage = requestWidth / sourceWidth - let heightPercentage = requestHeight / sourceHeight - return Math.min(widthPercentage, heightPercentage) - } -} - -/*不进行下采样*/ -@Sendable -export class DownsampleNone implements BaseDownsampling { - getName() { - return "DownsampleNone" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - //下采样因子 - return 1 - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - //下采样因子 - return 1 - } -} - -/* 下采样使得图像的组大尺寸在给定的尺寸的1/2之间*/ -@Sendable -export class AtMost implements BaseDownsampling { - getName() { - return "AtMost" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - let maxIntegerFactor = Math.ceil(Math.max(sourceHeight / requestHeight, sourceWidth / requestWidth)); - let lesserOrEqualSampleSize = Math.max(1, this.highestOneBit(maxIntegerFactor)) - let greaterOrEqualSampleSize = lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0) - return 1 / greaterOrEqualSampleSize - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - return 0 - } - - highestOneBit(i: number): number { - i |= (i >> 1); - i |= (i >> 2); - i |= (i >> 4); - i |= (i >> 8); - i |= (i >> 16); - return i - (i >>> 1); - } -} - -@Sendable -export class Atleast implements BaseDownsampling { - getName() { - return "Atleast" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - let minIntegerFactor = Math.floor(Math.min(sourceHeight / requestHeight, sourceWidth / requestWidth)) - return minIntegerFactor == 0 ? 1 : 1 / this.highestOneBit(minIntegerFactor) - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - //下采样因子 - return 1 - } - - highestOneBit(i: number): number { - i |= (i >> 1); - i |= (i >> 2); - i |= (i >> 4); - i |= (i >> 8); - i |= (i >> 16); - return i - (i >>> 1); - } -} - -@Sendable -export class CenterOutside implements BaseDownsampling { - getName() { - return "CenterOutside" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - let widthPercentage = requestWidth / sourceWidth - let heightPercentage = requestHeight / sourceHeight - return Math.max(widthPercentage, heightPercentage) - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - //下采样因子 - return 1 - } -} +import { BaseDownsampling } from './BaseDownsampling'; +import { highestOneBit, SampleSizeRounding } from './downsampleUtils'; +//FitCenter类实现DownsampleStartegy @Sendable export class FitCenter implements BaseDownsampling { getName() { return "FitCenter" } - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - let widthPercentage = requestWidth / sourceWidth - let heightPercentage = requestHeight / sourceHeight - return Math.min(widthPercentage, heightPercentage) + //实现 getScaleFactor 方法 + getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth); + const a = maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor) + return a; } - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number): number { - //下采样因子 - return 1 + getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + + return SampleSizeRounding.MEMORY; } } -export enum SampleSizeRounding { - MEMORY, - QUALITY +//None 类实现 DownsampleStrategy 接口 +@Sendable +export class DownsampleNone implements BaseDownsampling { + getName(): string { + return "DownsampleNone" + } + + //实现 getScaleFactor 方法 + public getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + //不进行任何下采样,缩放因子为 1 + return 1; + } + + //实现 getSampleSizeRounding 方法 + public getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): SampleSizeRounding { + //总是返回 QUALITY + return SampleSizeRounding.QUALITY + + } +} + + +/*宽高进行等比缩放宽高里面最小的比例先放进去然后再更据原图的缩放比去适配另一边*/ +@Sendable +export class CenterOutside implements BaseDownsampling { + getName() { + return "CenterOutside" + } + + //实现 getScaleFactor 方法 + getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + const widthPercentage = requestedWidth / sourceWidth; + const heightPercentage = requestedHeight / sourceHeight; + //返回宽度和高度比例中最大的值 + return Math.max(widthPercentage, heightPercentage); + } + + //实现 getSampleSizeRounding 方法 + getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): SampleSizeRounding { + //根据 CenterOutside 的逻辑,总是返回 QUALITY + return SampleSizeRounding.QUALITY; + } +} + +/*请求尺寸大于实际尺寸不进行放大,按照原图展示*/ +@Sendable +export class Atleast implements BaseDownsampling { + + getName() { + return "AtLeast" + } + + //实现 getScaleFactor 方法 + public getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): SampleSizeRounding { + //计算最小整数因子 + const minIntegerFactor = Math.min(sourceHeight / requestedHeight, sourceWidth / requestedWidth) + //根据最小整数因子计算缩放因子 + return minIntegerFactor === 0 ? 1 : 1 / highestOneBit(minIntegerFactor); + } + + //实现 getSampleSizeRounding 方法 + public getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): SampleSizeRounding { + //总是返回 QUALITY + return SampleSizeRounding.QUALITY + } +} + +/*请求尺寸大于实际尺寸不进行放大,按照原图展示*/ +@Sendable +export class AtMost implements BaseDownsampling { + getName() { + return "AtMost" + } + + //实现 getScaleFactor 方法 + getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + const maxIntegerFactor = Math.ceil(Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth)); + let lesserOrEqualSampleSize = Math.max(1, highestOneBit(maxIntegerFactor)); + let greaterOrEqualSampleSize = lesserOrEqualSampleSize + greaterOrEqualSampleSize = lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0) + //返回缩放因子 + return 1 / greaterOrEqualSampleSize + } + //实现 getSampleSizeRounding 方法 + getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestHeight: number): SampleSizeRounding { + //根据 AtMost 的逻辑,总是返回 MEMORY + return SampleSizeRounding.MEMORY + } +} + +/*宽高进行等比缩放宽高里面最大的比例先放进去然后再更据原图的缩放比去适配另一边*/ +@Sendable +export class CenterInside implements BaseDownsampling { + getName() { + return "CenterInside" + } + + //实现 getScaleFactor 方法 + getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + //获取 FIT_CENTER 的缩放因子 + const fitCenterScaleFactor: ESObject = this.getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight); + //返回不超过 1 的缩放因子,即尽量缩小图像以适应目标尺寸,但不会放大 + return Math.min(1, fitCenterScaleFactor); + + } + + getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { + //类似 AT_LEAST + const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth); + return maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor); + } + + + //实现 getSampleSizeRounding 方法 + getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): SampleSizeRounding { + //如果缩放因子为 1,表示没有缩放,优先选择质量 + if (this.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight) === 1) { + return SampleSizeRounding.QUALITY + } + //否则,使用 FIL_CENTER 的 SampleSizeRounding 值 + return this.getSampleSize(sourceWidth, sourceHeight, requestedWidth, requestedHeight); + } + getSampleSize(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): SampleSizeRounding { + return SampleSizeRounding.MEMORY; + } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/downsampling/Downsampler.ets b/library/src/main/ets/components/imageknife/downsampling/Downsampler.ets index 41aeabb..c97f2cf 100644 --- a/library/src/main/ets/components/imageknife/downsampling/Downsampler.ets +++ b/library/src/main/ets/components/imageknife/downsampling/Downsampler.ets @@ -14,13 +14,8 @@ */ import { RequestOption } from '../RequestOption'; import { FileTypeUtil } from '../utils/FileTypeUtil'; -import { CenterOutside, FitCenter, SampleSizeRounding } from './DownsampleStartegy'; - -let TAG = 'downsampling' -export interface calculateScaleType { - targetWidth: number, - targetHeight: number -} +import { Atleast, AtMost, CenterInside, CenterOutside, DownsampleNone, FitCenter } from './DownsampleStartegy'; +import { calculateScaleType, highestOneBit, SampleSizeRounding } from './downsampleUtils'; export class Downsampler { @@ -29,40 +24,79 @@ export class Downsampler { sourceHeight: number, sourceWidth: number, request?: RequestOption - ): calculateScaleType { - const fileType: string | null = new FileTypeUtil().getFileType(imageType) - let powerOfTwoWidth: number | null = null; - let powerOfTwoHeight: number | null = null; + ): ESObject { + let degreesToRotate:number = 90 //角度 + const fileType: string | null = new FileTypeUtil().getFileType(imageType)//获取图片类型 + let powerOfTwoWidth: number = 0; + let powerOfTwoHeight: number = 0; let targetWidth: number = 0 let targetHeight: number = 0 + if (sourceWidth <= 0 || sourceHeight <= 0) { + throw new Error("Cannot found width or height "); + }; + let orientedSourceWidth = sourceWidth; + let orientedSourceHeight = sourceHeight; + if (this.isRotationRequired(degreesToRotate)) { + orientedSourceWidth = sourceHeight; + orientedSourceHeight = sourceWidth; + } if (request?.size.width && !request?.size.height) { targetWidth = this.round((request?.size.height) * sourceWidth / sourceHeight) } else if (request?.size.height && !request?.size.width) { targetHeight = this.round((request?.size.width) * sourceHeight / sourceWidth) } else if (request?.size.height && request?.size.width) { - targetHeight = request.size.height; - targetWidth = request?.size.width; + targetWidth = request?.size.width===sourceWidth?(this.isRotationRequired(degreesToRotate)?sourceHeight:sourceWidth):request?.size.width + targetHeight = request?.size.height===sourceHeight?(this.isRotationRequired(degreesToRotate)?sourceWidth:sourceHeight):request?.size.height; } else { throw new Error("Cannot found width or height "); } - if (sourceWidth <= 0 || sourceHeight <= 0){ - throw new Error("Cannot found width or height"); - }; - let orientedSourceWidth = sourceWidth; - let orientedSourceHeight = sourceHeight; - if (this.isRotationRequired(90)) { - orientedSourceWidth = sourceHeight; - orientedSourceHeight = sourceWidth; - } /*安卓的模式*/ let exactScaleFactor: number = new FitCenter() .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - if (exactScaleFactor <= 0) { - throw new Error("Cannot round with exactScaleFactor"); - } /*安卓的模式*/ let rounding: SampleSizeRounding = new FitCenter() .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + switch (request?.downsampType.getName()) { + case "FitCenter": + exactScaleFactor = new FitCenter() + .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + rounding = new FitCenter() + .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + break; + case "DownsampleNone": + exactScaleFactor = new DownsampleNone() + .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + rounding = new DownsampleNone() + .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + break + case "AtMost": + exactScaleFactor = new AtMost() + .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + rounding = new AtMost() + .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + break + case "CenterInside": + exactScaleFactor = new CenterInside() + .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + rounding = new CenterInside() + .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + break + case "AtLeast": + exactScaleFactor = new Atleast() + .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + rounding = new Atleast() + .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + break + case "CenterOutside": + exactScaleFactor = new CenterOutside() + .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + rounding = new CenterOutside() + .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) + break + } + if (exactScaleFactor <= 0) { + throw new Error("Cannot round with exactScaleFactor"); + } if (rounding == null) { throw new Error("Cannot round with null rounding"); } @@ -75,7 +109,7 @@ export class Downsampler { Math.min(widthScaleFactor, heightScaleFactor) // 将整型的缩放因子转换为2的次幂采样大小 let powerOfTwoSampleSize: number = 0; - powerOfTwoSampleSize = Math.max(1, this.highestOneBit(scaleFactor)) + powerOfTwoSampleSize = Math.max(1, highestOneBit(scaleFactor)) if (rounding == SampleSizeRounding.MEMORY && powerOfTwoSampleSize < (1 / exactScaleFactor)) { powerOfTwoSampleSize = powerOfTwoSampleSize << 1; } @@ -103,15 +137,6 @@ export class Downsampler { return a } - highestOneBit(i: number): number { - i |= (i >> 1); - i |= (i >> 2); - i |= (i >> 4); - i |= (i >> 8); - i |= (i >> 16); - return i - (i >>> 1); - } - round(value: number): number { return Math.floor(value + 0.5); } @@ -119,16 +144,4 @@ export class Downsampler { isRotationRequired(degreesToRotate: number): boolean { return degreesToRotate == 90 || degreesToRotate == 270; } - - getDensityMultiplier(adjustedScaleFactor: number): number { - return Math.round(Number.MAX_VALUE * (adjustedScaleFactor <= 1 ? adjustedScaleFactor : 1 / adjustedScaleFactor)); - } - - adjustTargetDensityForError(adjustedScaleFactor: number): number { - let densityMultiplier = this.getDensityMultiplier(adjustedScaleFactor); - let targetDensity = this.round(densityMultiplier * adjustedScaleFactor); - let scaleFactorWithError = targetDensity / densityMultiplier; - let difference = adjustedScaleFactor / scaleFactorWithError; - return this.round(difference * targetDensity); - } } \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/downsampling/downsampleUtils.ets b/library/src/main/ets/components/imageknife/downsampling/downsampleUtils.ets new file mode 100644 index 0000000..cf5148b --- /dev/null +++ b/library/src/main/ets/components/imageknife/downsampling/downsampleUtils.ets @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export enum SampleSizeRounding { + //内存优先 + QUALITY, + //质量优先 + MEMORY +} + +export function highestOneBit(i: number): number { + i |= (i >> 1); + i |= (i >> 2); + i |= (i >> 4); + i |= (i >> 8); + i |= (i >> 16); + return i - (i >>> 1); +} + +export interface calculateScaleType { + targetWidth: number, + targetHeight: number +} \ No newline at end of file diff --git a/library/src/main/ets/components/imageknife/utils/ParseImageUtil.ets b/library/src/main/ets/components/imageknife/utils/ParseImageUtil.ets index eac523b..c97c54f 100644 --- a/library/src/main/ets/components/imageknife/utils/ParseImageUtil.ets +++ b/library/src/main/ets/components/imageknife/utils/ParseImageUtil.ets @@ -17,7 +17,8 @@ import { IParseImage } from '../interface/IParseImage' import image from '@ohos.multimedia.image'; import { BusinessError } from '@ohos.base' import { RequestOption } from '../RequestOption'; -import {Downsampler,calculateScaleType } from '../downsampling/Downsampler'; +import { Downsampler } from '../downsampling/Downsampler'; +import { calculateScaleType } from '../downsampling/downsampleUtils'; export class ParseImageUtil implements IParseImage { parseImage( @@ -43,9 +44,9 @@ export class ParseImageUtil implements IParseImage { editable: true, desiredSize: defaultSize }; - if(request?.downsampType.getName()!==undefined && request?.downsampType.getName()!=='DownsampleNone'){ - const b:calculateScaleType = new Downsampler().calculateScaling(imageinfo, hValue, wValue,request) - opts= { + if (request?.downsampType.getName() !== undefined && request?.downsampType.getName() !== 'DownsampleNone') { + const b: calculateScaleType = new Downsampler().calculateScaling(imageinfo, hValue, wValue, request) + opts = { editable: true, desiredSize: { height: b.targetHeight, diff --git a/library/src/main/ets/components/imageknife/utils/gif/GIFParseImpl.ets b/library/src/main/ets/components/imageknife/utils/gif/GIFParseImpl.ets index 9c4ea5f..0da3888 100644 --- a/library/src/main/ets/components/imageknife/utils/gif/GIFParseImpl.ets +++ b/library/src/main/ets/components/imageknife/utils/gif/GIFParseImpl.ets @@ -20,7 +20,8 @@ import worker, { ErrorEvent, MessageEvents } from '@ohos.worker'; import taskpool from '@ohos.taskpool' import { LogUtil } from '../LogUtil' import { RequestOption } from '../../RequestOption' -import { Downsampler,calculateScaleType } from '../../downsampling/Downsampler' +import { Downsampler } from '../../downsampling/Downsampler' +import { calculateScaleType } from '../../downsampling/downsampleUtils' export interface senderData { type: string, @@ -53,7 +54,7 @@ export class GIFParseImpl implements IParseGif { imageSource.getImageInfo().then((value) => { hValue = Math.round(value.size.height); wValue = Math.round(value.size.height); - if ( _request?.downsampType.getName()!==undefined && _request?.downsampType.getName()!=='DownsampleNone') { + if (_request?.downsampType.getName() !== undefined && _request?.downsampType.getName() !== 'DownsampleNone') { const b: calculateScaleType = new Downsampler().calculateScaling(imageinfo, Math.round(value.size.height), Math.round(value.size.width), _request) decodeOpts = { sampleSize: 1, diff --git a/library/src/main/ets/components/imageknife/utils/svg/SVGParseImpl.ets b/library/src/main/ets/components/imageknife/utils/svg/SVGParseImpl.ets index e7df537..760021c 100644 --- a/library/src/main/ets/components/imageknife/utils/svg/SVGParseImpl.ets +++ b/library/src/main/ets/components/imageknife/utils/svg/SVGParseImpl.ets @@ -17,7 +17,8 @@ import { RequestOption } from '../../RequestOption' import { BusinessError } from '@ohos.base' import { ImageKnifeData, ImageKnifeType } from '../../ImageKnifeData' import image from '@ohos.multimedia.image' -import { Downsampler, calculateScaleType } from '../../downsampling/Downsampler' +import { Downsampler } from '../../downsampling/Downsampler' +import { calculateScaleType } from '../../downsampling/downsampleUtils' export class SVGParseImpl implements IParseSvg { parseSvg(option: RequestOption, imageInfo: ArrayBuffer,