diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3dbb6..29cc918 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,6 @@ - 修复加载错误图后未去请求排队队列中的请求 - 子线程本地Resource参数类型转换成number - 修改使用hilog记录日志,默认打开debug级别的日志 -- 增加降采样 - file格式图片,fd同步close - 解码pixelMap默认不可编辑,图形变化可编辑 - 修改网络请求超时设置 diff --git a/README.md b/README.md index 73c79ba..1e232d7 100644 --- a/README.md +++ b/README.md @@ -264,20 +264,8 @@ ImageKnifeAnimatorComponent({ }),animatorOption:this.animatorOption }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) ``` -#### 11.图片降采样 示例 -``` -ImageKnifeComponent({ - imageKnifeOption:new ImageKnifeOption({ - loadSrc:$r("app.media.pngSample"), - placeholderSrc:$r('app.media.loading'), - errorholderSrc:$r('app.media.failed'), - downsampleOf: DownsampleStrategy.NONE - }),animatorOption:this.animatorOption - }).width(300).height(300) -``` #### 复用场景 在aboutToRecycle生命周期清空组件内容;通过watch监听触发图片的加载。 - ## 接口说明 ### ImageKnife组件 | 组件名称 | 入参内容 | 功能简介 | @@ -320,17 +308,7 @@ ImageKnifeComponent({ | drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) | | onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) | | onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 | -| downsampleOf | DownsampleStrategy | 降采样(可选) | -### 降采样类型 -| 类型 | 相关描述 | -|---------------------|-------------------| -| NONE | 不进行降采样 | -| AT_MOST | 请求尺寸大于实际尺寸不进行放大 | -| FIT_CENTER_MEMORY | 两边自适应内存优先 | -| FIT_CENTER_QUALITY | 两边自适应质量优先 | -| CENTER_INSIDE_MEMORY | 宽高缩放比最大的比例,进行缩放适配内存优先 | -| CENTER_INSIDE_QUALITY | 宽高缩放比最大的比例,进行缩放适配质量优先 | -| CENTER_OUTSIDE | 根据宽高的最小的比例,进行适配 | + ### ImageKnife接口 | 参数名称 | 入参内容 | 功能简介 | diff --git a/entry/src/main/ets/pages/DownSamplePage.ets b/entry/src/main/ets/pages/DownSamplePage.ets deleted file mode 100644 index b8cc0e6..0000000 --- a/entry/src/main/ets/pages/DownSamplePage.ets +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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. - */ -import { DownsampleStrategy, ImageKnifeOption, } from '@ohos/imageknife'; -import { ImageKnifeComponent, BlurTransformation, } from '@ohos/libraryimageknife'; -import { image } from '@kit.ImageKit'; -import { BusinessError } from '@kit.BasicServicesKit'; -import { Downsampler } from '@ohos/imageknife/src/main/ets/downsampling/Downsampler'; -import { FileTypeUtil } from '@ohos/imageknife/src/main/ets/utils/FileTypeUtil'; - -@Entry -@ComponentV2 -struct DownSamplePage { - @Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption( { - loadSrc: $r('app.media.startIcon'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain - }) - isBrightness: boolean = false - @Local beforeSampling: number = 0 - @Local afterSampling: number = 0 - @Local SamplingList: SamplingType[] = [ - new SamplingType(0, "NONE"), - new SamplingType(1, "AT_MOST"), - new SamplingType(2, "FIT_CENTER_MEMORY"), - new SamplingType(4, "FIT_CENTER_QUALITY"), - new SamplingType(5, "CENTER_INSIDE_MEMORY"), - new SamplingType(6, "CENTER_INSIDE_QUALITY"), - new SamplingType(7, "CENTER_OUTSIDE"), - ] - @Local checked: boolean = false - - updateImageKnifeOption(value: string) { - if (value === 'NONE') { - this.imageKnifeOption =new ImageKnifeOption( { - loadSrc: $r('app.media.jpgSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.NONE - }) - this.originalPixMap($r('app.media.jpgSample')) - this.afterSamplingFunc($r('app.media.jpgSample')) - } else if (value === 'AT_MOST') { - this.imageKnifeOption =new ImageKnifeOption( { - loadSrc: $r('app.media.svgSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.AT_MOST - }) - this.originalPixMap($r('app.media.svgSample')) - this.afterSamplingFunc($r('app.media.svgSample')) - } else if (value === 'FIT_CENTER_MEMORY') { - this.imageKnifeOption =new ImageKnifeOption( { - loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.FIT_CENTER_MEMORY - }) - this.originalPixMap($r('app.media.pngSample')) - this.afterSamplingFunc($r('app.media.pngSample')) - } - else if (value ==='FIT_CENTER_QUALITY') { - this.imageKnifeOption =new ImageKnifeOption( { - loadSrc: $r('app.media.pngSample'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.FIT_CENTER_QUALITY - }) - this.originalPixMap($r('app.media.pngSample')) - this.afterSamplingFunc($r('app.media.pngSample')) - } - else if (value === 'CENTER_INSIDE_MEMORY') { - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: $r('app.media.jpgSample1'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.CENTER_INSIDE_MEMORY - }) - this.originalPixMap($r('app.media.jpgSample1')) - this.afterSamplingFunc($r('app.media.jpgSample1')) - } else if (value === 'CENTER_INSIDE_QUALITY') { - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: $r('app.media.jpgSample1'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.CENTER_INSIDE_QUALITY - }) - this.originalPixMap($r('app.media.jpgSample1')) - this.afterSamplingFunc($r('app.media.jpgSample1')) - } - else { - this.imageKnifeOption = new ImageKnifeOption({ - loadSrc: $r('app.media.jpgSample2'), - placeholderSrc: $r("app.media.loading"), - errorholderSrc: $r("app.media.app_icon"), - objectFit: ImageFit.Contain, - downsampleOf: DownsampleStrategy.CENTER_OUTSIDE - }) - this.originalPixMap($r('app.media.jpgSample2')) - this.afterSamplingFunc($r('app.media.jpgSample2')) - } - } - - async afterSamplingFunc(imgs: Resource) { - let img: Uint8Array = await getContext(this).resourceManager.getMediaContent(imgs); - let imageSource: image.ImageSource = image.createImageSource(img.buffer.slice(0)); - let fileTypeUtil = new FileTypeUtil(); - let typeValue = fileTypeUtil.getFileType(img.buffer.slice(0)); - let decodingOptions: image.DecodingOptions = { - editable: true, - desiredPixelFormat: 3, - } - let imageInfo = await imageSource.getImageInfo() - let reqSize = - new Downsampler().calculateScaling(typeValue, imageInfo.size.width, imageInfo.size.height, 300, - 300, this.imageKnifeOption.downsampleOf) - decodingOptions = { - editable: true, - desiredSize: { - width: reqSize.targetWidth, - height: reqSize.targetHeight - } - } - // 创建pixelMap - imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => { - this.afterSampling = pixelMap.getPixelBytesNumber() - }).catch((err: BusinessError) => { - console.error("Failed to create PixelMap") - }); - } - - async originalPixMap(imgs: Resource,) { - let img: Uint8Array = await getContext(this).resourceManager.getMediaContent(imgs); - let imageSource: image.ImageSource = image.createImageSource(img.buffer.slice(0)); - let decodingOptions: image.DecodingOptions = { - editable: true, - desiredPixelFormat: 3, - } - // 创建pixelMap - imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => { - this.beforeSampling = pixelMap.getPixelBytesNumber() - }).catch((err: BusinessError) => { - console.error("Failed to create PixelMap") - }); - } - - build() { - Scroll() { - Column() { - ForEach(this.SamplingList, (item: SamplingType, index) => { - Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { - Radio({ value: item.value + 'radio', group: 'radioGroup' }) - .height(50) - .width(50) - .checked(this.checked) - .onClick(() => { - this.updateImageKnifeOption(item.value) - }) - Text("降采样规格:" + item.value).fontSize(20) - } - }, (item: SamplingType) => JSON.stringify(item)) - Column() { - Text(`未降采样大小:${this.beforeSampling}`).fontSize(20) - Text(`降采样后大小:${this.afterSampling}`).fontSize(20) - } - - ImageKnifeComponent({ - imageKnifeOption: this.imageKnifeOption - }) - .height(300) - .width(300) - .borderWidth(1) - .borderColor(Color.Pink) - } - - } - .height('100%') - .width('100%') - } -} - -class SamplingType { - key: number - value: string - - constructor(key: number, value: string) { - this.key = key - this.value = value - } -} \ No newline at end of file diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index cbc4c7e..f6d2a5e 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -47,11 +47,6 @@ struct Index { }); }) - Button("降采样").margin({top:10}).onClick(() => { - router.push({ - uri: 'pages/DownSamplePage', - }); - }) Button("单个图片使用").margin({top:10}).onClick(()=>{ router.push({ uri: 'pages/SingleImage', diff --git a/entry/src/main/resources/base/media/jpgSample.jpg b/entry/src/main/resources/base/media/jpgSample.jpg deleted file mode 100644 index c259cdc..0000000 Binary files a/entry/src/main/resources/base/media/jpgSample.jpg and /dev/null differ diff --git a/entry/src/main/resources/base/media/jpgSample1.jpg b/entry/src/main/resources/base/media/jpgSample1.jpg deleted file mode 100644 index a4aa87b..0000000 Binary files a/entry/src/main/resources/base/media/jpgSample1.jpg and /dev/null differ diff --git a/entry/src/main/resources/base/media/jpgSample2.jpg b/entry/src/main/resources/base/media/jpgSample2.jpg deleted file mode 100644 index 33c27f7..0000000 Binary files a/entry/src/main/resources/base/media/jpgSample2.jpg and /dev/null differ diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 534b53b..de593dd 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -23,7 +23,6 @@ "pages/ImageAnimatorPage", "pages/TestSetCustomImagePage", "pages/TestErrorHolderPage", - "pages/TestTaskResourcePage", - "pages/DownSamplePage" + "pages/TestTaskResourcePage" ] } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/List.test.ets b/entry/src/ohosTest/ets/test/List.test.ets index 51a0c15..8c04309 100644 --- a/entry/src/ohosTest/ets/test/List.test.ets +++ b/entry/src/ohosTest/ets/test/List.test.ets @@ -18,7 +18,6 @@ import ImageKnifeOptionTest from './ImageKnifeOption.test'; import MemoryLruCacheTest from './MemoryLruCache.test'; import ImageKnifeTest from './ImageKnife.test'; import Transform from './transform.test'; -import SamplingTest from './SamplingTest.test'; export default function testsuite() { MemoryLruCacheTest(); @@ -27,5 +26,4 @@ export default function testsuite() { ImageKnifeOptionTest(); ImageKnifeTest(); Transform(); - SamplingTest() } \ No newline at end of file diff --git a/entry/src/ohosTest/ets/test/SamplingTest.test.ets b/entry/src/ohosTest/ets/test/SamplingTest.test.ets deleted file mode 100644 index 8fe3093..0000000 --- a/entry/src/ohosTest/ets/test/SamplingTest.test.ets +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' -import { image } from '@kit.ImageKit' -import { BusinessError } from '@kit.BasicServicesKit' -import { calculateScaleType, Downsampler } from '@ohos/imageknife/src/main/ets/downsampling/Downsampler' -import { DownsampleStrategy } from '@ohos/imageknife' - -export default function SamplingTest() { - describe('SamplingTest', () => { - // Defines a test suite. Two parameters are supported: test suite name and test suite function. - beforeAll(() => { - // Presets an action, which is performed only once before all test cases of the test suite start. - // This API supports only one parameter: preset action function. - }) - beforeEach(() => { - // Presets an action, which is performed before each unit test case starts. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: preset action function. - }) - afterEach(() => { - // Presets a clear action, which is performed after each unit test case ends. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: clear action function. - }) - afterAll(() => { - // Presets a clear action, which is performed after all test cases of the test suite end. - // This API supports only one parameter: clear action function. - }) - it('NONE', 0, () => { - let reqSize: calculateScaleType = - new Downsampler().calculateScaling('jpg', 1024, 1024, 200, - 200, DownsampleStrategy.NONE, false) - let req = (reqSize.targetWidth == 1024 && reqSize.targetHeight == 1024) - expect(req).assertEqual(true); - }) - it('AT_MOST', 1, () => { - let reqSize: calculateScaleType = - new Downsampler().calculateScaling('jpg', 1024, 1024, 200, - 200, DownsampleStrategy.AT_MOST, false) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) - expect(req).assertEqual(true); - }) - it('FIT_CENTER', 2, () => { - let reqSize: calculateScaleType = - new Downsampler().calculateScaling('jpg', 1024, 1024, 200, - 200, DownsampleStrategy.FIT_CENTER, false) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) - expect(req).assertEqual(true); - }) - it('CENTER_INSIDE', 3, () => { - let reqSize: calculateScaleType = - new Downsampler().calculateScaling('jpg', 1024, 1024, 200, - 200, DownsampleStrategy.CENTER_INSIDE, false) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) - expect(req).assertEqual(true); - }) - it('CENTER_OUTSIDE', 4, () => { - let reqSize: calculateScaleType = - new Downsampler().calculateScaling('jpg', 1024, 1024, 200, - 200, DownsampleStrategy.CENTER_OUTSIDE, false) - let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024) - expect(req).assertEqual(true); - }) - - }) -} diff --git a/library/index.ets b/library/index.ets index acdeb60..4576c08 100644 --- a/library/index.ets +++ b/library/index.ets @@ -66,6 +66,4 @@ export { CropTransformation } from './src/main/ets/transform/CropTransformation' export { MaskTransformation } from './src/main/ets/transform/MaskTransformation' -export { SepiaTransformation } from './src/main/ets/transform/SepiaTransformation' - -export { DownsampleStrategy } from './src/main/ets/downsampling/DownsampleStartegy' \ No newline at end of file +export { SepiaTransformation } from './src/main/ets/transform/SepiaTransformation' \ No newline at end of file diff --git a/library/src/main/ets/ImageKnifeDispatcher.ets b/library/src/main/ets/ImageKnifeDispatcher.ets index 2fc5d4f..2791464 100644 --- a/library/src/main/ets/ImageKnifeDispatcher.ets +++ b/library/src/main/ets/ImageKnifeDispatcher.ets @@ -40,8 +40,6 @@ import { } from './model/ImageKnifeData' import { combineArrayBuffers } from './model/utils'; import { BusinessError } from '@kit.BasicServicesKit'; -import { Downsampler } from './downsampling/Downsampler'; -import { DownsampleStrategy } from './downsampling/DownsampleStartegy'; export class ImageKnifeDispatcher { // 最大并发 @@ -191,10 +189,7 @@ export class ImageKnifeDispatcher { fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(), isAnimator:isAnimator, moduleName: moduleName == "" ? undefined : moduleName, - resName: resName == "" ? undefined : resName, - targetWidth: currentRequest.componentWidth, - targetHeight: currentRequest.componentHeight, - downsampType: currentRequest.imageKnifeOption.downsampleOf, + resName: resName == "" ? undefined : resName } if(request.customGetImage == undefined) { @@ -209,7 +204,7 @@ export class ImageKnifeDispatcher { emitter.on(Constants.PROGRESS_EMITTER + memoryKey, (data) => { this.progressCallBack(requestList! , data?.data?.value as number) }); - } + } LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start:" + currentRequest.imageKnifeOption.loadSrc) taskpool.execute(task).then((res: Object) => { @@ -345,8 +340,8 @@ export class ImageKnifeDispatcher { } } else { if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) { - // 回调请求成功 - requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") + // 回调请求成功 + requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") } } }); @@ -489,7 +484,7 @@ async function requestJob(request: RequestJobRequest, requestList?: List { loadError = err.message; @@ -510,21 +505,21 @@ async function requestJob(request: RequestJobRequest, requestList?: List { - await fs.stat(file.fd).then(async (stat) =>{ - let buf = new ArrayBuffer(stat.size); - await fs.read(file.fd, buf).then((readLen) => { - resBuf = buf; - fs.closeSync(file.fd); + await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => { + await fs.stat(file.fd).then(async (stat) =>{ + let buf = new ArrayBuffer(stat.size); + await fs.read(file.fd, buf).then((readLen) => { + resBuf = buf; + fs.close(file.fd); + }).catch((err:BusinessError) => { + loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code; + }) }).catch((err:BusinessError) => { - loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code; + loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code; }) }).catch((err:BusinessError) => { - loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code; + loadError ='LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code; }) - }).catch((err:BusinessError) => { - loadError ='LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code; - }) } else { //从本地文件获取 try { let stat = fs.statSync(request.src); @@ -656,20 +651,6 @@ async function requestJob(request: RequestJobRequest, requestList?: List { resPixelmap = pixelmap @@ -682,22 +663,6 @@ async function requestJob(request: RequestJobRequest, requestList?: List { diff --git a/library/src/main/ets/ImageKnifeOption.ets b/library/src/main/ets/ImageKnifeOption.ets index 670180d..3a9bf6f 100644 --- a/library/src/main/ets/ImageKnifeOption.ets +++ b/library/src/main/ets/ImageKnifeOption.ets @@ -16,7 +16,6 @@ import taskpool from '@ohos.taskpool'; import common from '@ohos.app.ability.common' import { CacheStrategy, ImageKnifeData,EventImage } from './model/ImageKnifeData'; import { PixelMapTransformation } from './transform/PixelMapTransformation'; -import { DownsampleStrategy } from './downsampling/DownsampleStartegy'; import { drawing } from '@kit.ArkGraphics2D'; export interface HeaderOptions { @@ -91,8 +90,6 @@ interface ImageOption { onLoadListener?: OnLoadCallBack | undefined; onComplete?:(event:EventImage | undefined) => void drawingColorFilter?: ColorFilter | drawing.ColorFilter - downsampleOf?: DownsampleStrategy - } @ObservedV2 export class ImageKnifeOption { @@ -124,9 +121,6 @@ export class ImageKnifeOption { onLoadListener?: OnLoadCallBack | undefined; onComplete?:(event:EventImage | undefined) => void drawingColorFilter?: ColorFilter | drawing.ColorFilter - // 下采样 - downsampleOf?: DownsampleStrategy = DownsampleStrategy.NONE - constructor(option?:ImageOption) { this.loadSrc = option?.loadSrc == undefined ? "" : option?.loadSrc this.placeholderSrc = option?.placeholderSrc @@ -147,7 +141,6 @@ export class ImageKnifeOption { this.onLoadListener = option?.onLoadListener this.onComplete = option?.onComplete this.drawingColorFilter = option?.drawingColorFilter - this.downsampleOf = option?.downsampleOf } } diff --git a/library/src/main/ets/ImageKnifeRequest.ets b/library/src/main/ets/ImageKnifeRequest.ets index d981ec8..cb2115b 100644 --- a/library/src/main/ets/ImageKnifeRequest.ets +++ b/library/src/main/ets/ImageKnifeRequest.ets @@ -15,7 +15,7 @@ import { ImageKnifeOption } from './ImageKnifeOption'; import common from '@ohos.app.ability.common'; import { ImageKnifeRequestSource } from './model/ImageKnifeData'; -import { DownsampleStrategy } from './downsampling/DownsampleStartegy'; + export class ImageKnifeRequest { requestState: ImageKnifeRequestState = ImageKnifeRequestState.PROGRESS @@ -27,22 +27,18 @@ export class ImageKnifeRequest { ImageKnifeRequestCallback: ImageKnifeRequestCallback componentVersion: number = 0 headers: Map = new Map() - downsampType?: DownsampleStrategy constructor(option: ImageKnifeOption, - uIAbilityContext: common.UIAbilityContext, - width: number, - height: number, - version: number, - ImageKnifeRequestCallback: ImageKnifeRequestCallback, - downsampType?: DownsampleStrategy, - ) { + uIAbilityContext: common.UIAbilityContext, + width: number, + height: number, + version: number, + ImageKnifeRequestCallback: ImageKnifeRequestCallback) { this.imageKnifeOption = option this.context = uIAbilityContext this.componentWidth = width this.componentHeight = height this.componentVersion = version this.ImageKnifeRequestCallback = ImageKnifeRequestCallback - this.downsampType = downsampType } // RequestOption调用header对于的方法 addHeader(key: string, value: Object) { diff --git a/library/src/main/ets/downsampling/BaseDownsampling.ets b/library/src/main/ets/downsampling/BaseDownsampling.ets deleted file mode 100644 index 5b49b68..0000000 --- a/library/src/main/ets/downsampling/BaseDownsampling.ets +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ -import { DownsampleStrategy } from './DownsampleStartegy'; - -import { SampleSizeRounding } from './DownsampleUtils'; - -export interface BaseDownsampling { - getName(): string - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number,downsampType?:DownsampleStrategy): number - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number, - requestHeight: number,downsampType?:DownsampleStrategy): SampleSizeRounding -} \ No newline at end of file diff --git a/library/src/main/ets/downsampling/DownsampleStartegy.ets b/library/src/main/ets/downsampling/DownsampleStartegy.ets deleted file mode 100644 index 3de4efb..0000000 --- a/library/src/main/ets/downsampling/DownsampleStartegy.ets +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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. - */ -import { BaseDownsampling } from './BaseDownsampling'; -import { highestOneBit, SampleSizeRounding } from './DownsampleUtils'; - -export class FitCenter implements BaseDownsampling { - getName() { - return "FitCenter" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy - ): number { - if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) { - const widthPercentage = requestedWidth / sourceWidth - const heightPercentage = requestedHeight / sourceHeight - return Math.min(widthPercentage, heightPercentage) - } else { - const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth); - const a = maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor) - return a; - } - } - - //实现 getSampleSizeRounding 方法 - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy - ): number { - if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) { - return SampleSizeRounding.QUALITY; - } else { - return SampleSizeRounding.MEMORY; - } - - } -} - -export class None implements BaseDownsampling { - getName(): string { - return "DownsampleNone" - } - - 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 { - return SampleSizeRounding.QUALITY - - } -} - - -/*宽高进行等比缩放宽高里面最小的比例先放进去 -然后再更据原图的缩放比去适配另一边*/ - -export class CenterOutside implements BaseDownsampling { - getName() { - return "CenterOutside" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number { - const widthPercentage = requestedWidth / sourceWidth; - const heightPercentage = requestedHeight / sourceHeight; - //返回宽度和高度比例中最大的值 - return Math.max(widthPercentage, heightPercentage); - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, - requestedHeight: number): SampleSizeRounding { - //根据 CenterOutside 的逻辑,总是返回 QUALITY - return SampleSizeRounding.QUALITY; - } -} - -/*请求尺寸大于实际尺寸不进行放大,按照原图展示*/ - -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 - if (lesserOrEqualSampleSize < maxIntegerFactor) { - greaterOrEqualSampleSize = lesserOrEqualSampleSize <<= 1; - } - greaterOrEqualSampleSize = lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0) - //返回缩放因子 - return 1 / greaterOrEqualSampleSize - } - - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, - requestHeight: number): SampleSizeRounding { - //根据 AtMost 的逻辑,总是返回 MEMORY - return SampleSizeRounding.MEMORY - } -} - -/*宽高进行等比缩放宽高里面最大的比例先放进去 -然后再更据原图的缩放比去适配另一边*/ -export class CenterInside implements BaseDownsampling { - getName() { - return "CenterInside" - } - - getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy - ): number { - //获取 FIT_CENTER 的缩放因子 - const fitCenterScaleFactor: ESObject = - this.getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType); - //返回不超过 1 的缩放因子,即尽量缩小图像以适应目标尺寸,但不会放大 - return Math.min(1, fitCenterScaleFactor); - - } - - getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy - ): number { - if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) { - const widthPercentage = requestedWidth / sourceWidth - const heightPercentage = requestedHeight / sourceHeight - return Math.min(widthPercentage, heightPercentage) - } else { - //类似 AT_LEAST,但只要求一个维度或另一个维度大于等于请求的尺寸 - const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth); - return maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor); - - } - } - - getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy - ): SampleSizeRounding { - //如果缩放因子为 1,表示没有缩放,优先选择质量 - if (this.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) === 1) { - return SampleSizeRounding.QUALITY - } - //否则,使用 FIL_CENTER 的 SampleSizeRounding 值 - return this.getSampleSize(sourceWidth, sourceHeight, requestedWidth, requestedHeight,downsampType); - } - - getSampleSize(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy - ): SampleSizeRounding { - if (downsampType===DownsampleStrategy.CENTER_INSIDE_QUALITY) { - return SampleSizeRounding.QUALITY; - } else { - return SampleSizeRounding.MEMORY; - } - } -} - -export enum DownsampleStrategy { - //请求尺寸大于实际尺寸不进行放大 - AT_MOST, - //两边自适应内存优先 - FIT_CENTER_MEMORY , - //两边自适应质量优先 - FIT_CENTER_QUALITY, - //按照宽高比的最大比进行适配内存优先 - CENTER_INSIDE_MEMORY , - //按照宽高比的最大比进行适配质量优先 - CENTER_INSIDE_QUALITY, - //宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配 - CENTER_OUTSIDE, - //不进行降采样 - NONE, -} \ No newline at end of file diff --git a/library/src/main/ets/downsampling/DownsampleUtils.ets b/library/src/main/ets/downsampling/DownsampleUtils.ets deleted file mode 100644 index ef17f42..0000000 --- a/library/src/main/ets/downsampling/DownsampleUtils.ets +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 { - /** - * Prefer to round the sample size up so that the image is downsampled to smaller than the - * requested size to use less memory. - */ - //(内存优先) - MEMORY, - /** - * Prefer to round the sample size down so that the image is downsampled to larger than the - * requested size to maintain quality at the expense of extra memory usage. - */ - //(质量优先) - QUALITY -} -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); -} \ No newline at end of file diff --git a/library/src/main/ets/downsampling/Downsampler.ets b/library/src/main/ets/downsampling/Downsampler.ets deleted file mode 100644 index b83918f..0000000 --- a/library/src/main/ets/downsampling/Downsampler.ets +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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. - */ -import { - AtMost, - CenterInside, - CenterOutside, - DownsampleStrategy, - FitCenter, - None, -} from './DownsampleStartegy'; -import { highestOneBit, SampleSizeRounding } from './DownsampleUtils'; - -export interface calculateScaleType { - targetWidth: number, - targetHeight: number -} - -export class Downsampler { - calculateScaling( - typeValue: string | null, - sourceHeight: number, //原始宽高 - sourceWidth: number | undefined, //原始宽高 - requestHeight: number, //请求宽高 - requestWidth: number, //请求宽高 - downsampType: DownsampleStrategy | undefined, - - ): calculateScaleType { - let degreesToRotate: ESObject = 90; - const fileType = typeValue //获取图片类型 - let powerOfTwoWidth: number | null = null; - let powerOfTwoHeight: number | null = null; - let targetWidth: number = 0 - let targetHeight: number = 0 - - if (sourceHeight <= 0 || sourceWidth == undefined || sourceWidth == null || sourceWidth <= 0) { - throw new Error("Cannot found width or height"); - } - let orientedSourceWidth = sourceWidth; - let orientedSourceHeight = sourceHeight; - if (this.isRotationRequired(degreesToRotate)) { - orientedSourceWidth = sourceHeight; - orientedSourceHeight = sourceWidth; - } - if (requestWidth && !requestHeight) { - targetWidth = this.round((requestHeight) * orientedSourceWidth / orientedSourceHeight) - } else if (requestHeight && !requestWidth) { - targetHeight = this.round((requestWidth) * orientedSourceHeight / orientedSourceWidth) - } else if (requestHeight && requestWidth) { - targetWidth = - requestHeight == sourceWidth ? (this.isRotationRequired(degreesToRotate) ? sourceHeight : sourceWidth) : - requestWidth; - targetHeight = - requestHeight == sourceHeight ? (this.isRotationRequired(degreesToRotate) ? sourceWidth : sourceHeight) : - requestWidth; - } else { - throw new Error("Cannot found width or height"); - } - let exactScaleFactor: number | undefined - let rounding: SampleSizeRounding | undefined - switch (downsampType) { - case DownsampleStrategy.FIT_CENTER_MEMORY || DownsampleStrategy.FIT_CENTER_QUALITY: - exactScaleFactor = new FitCenter() - .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType) - rounding = new FitCenter() - .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType) - break; - case DownsampleStrategy.NONE: - exactScaleFactor = new None() - .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - rounding = new None() - .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - break - case DownsampleStrategy.AT_MOST: - exactScaleFactor = new AtMost() - .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - rounding = new AtMost() - .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - break - case DownsampleStrategy.CENTER_INSIDE_MEMORY || DownsampleStrategy.CENTER_INSIDE_QUALITY: - exactScaleFactor = new CenterInside() - .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType) - rounding = new CenterInside() - .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType) - break - - case DownsampleStrategy.CENTER_OUTSIDE: - exactScaleFactor = new CenterOutside() - .getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - rounding = new CenterOutside() - .getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight) - break - } - if (exactScaleFactor==undefined|| exactScaleFactor <= 0 ) { - throw new Error("Cannot round with exactScaleFactor"); - } - if (rounding == undefined) { - throw new Error("Cannot round with null rounding"); - } - let outWidth: number = this.round(exactScaleFactor * orientedSourceWidth); - let outHeight: number = this.round(exactScaleFactor * orientedSourceHeight); - let widthScaleFactor = orientedSourceWidth / outWidth; - let heightScaleFactor = orientedSourceHeight / outHeight; - let scaleFactor = rounding ==SampleSizeRounding.QUALITY ? Math.max(widthScaleFactor, heightScaleFactor) : - Math.min(widthScaleFactor, heightScaleFactor) //将整型的缩放因子转换为2的次幂采样大小 - let powerOfTwoSampleSize: number = scaleFactor; - powerOfTwoSampleSize = Math.max(1, highestOneBit(scaleFactor)) - if (rounding == 1 && (powerOfTwoSampleSize < (1 / exactScaleFactor))) { - powerOfTwoSampleSize = powerOfTwoSampleSize << 1; - } - //基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸 - if (fileType === "png") { - powerOfTwoWidth = Math.floor(orientedSourceWidth / powerOfTwoSampleSize); - powerOfTwoHeight = Math.floor(orientedSourceHeight / powerOfTwoSampleSize); - } else if (fileType === "webp") { - powerOfTwoWidth = Math.round(orientedSourceWidth / powerOfTwoSampleSize); - powerOfTwoHeight = Math.round(orientedSourceHeight / powerOfTwoSampleSize); - } else { - powerOfTwoWidth = orientedSourceWidth / powerOfTwoSampleSize; - powerOfTwoHeight = orientedSourceHeight / powerOfTwoSampleSize; - } - let a: calculateScaleType = { - "targetWidth": powerOfTwoWidth, - "targetHeight": powerOfTwoHeight - } - return a - } - - round(value: number): number { - return Math.floor(value + 0.5); - } - - isRotationRequired(degreesToRotate: number): boolean { - return degreesToRotate == 90 || degreesToRotate == 270; - } -} diff --git a/library/src/main/ets/key/DefaultEngineKey.ets b/library/src/main/ets/key/DefaultEngineKey.ets index e2f48a7..6d43be1 100644 --- a/library/src/main/ets/key/DefaultEngineKey.ets +++ b/library/src/main/ets/key/DefaultEngineKey.ets @@ -17,7 +17,6 @@ import { ImageKnifeOption } from '../ImageKnifeOption'; import { IEngineKey } from './IEngineKey'; import { PixelMapTransformation } from '../transform/PixelMapTransformation'; import { ImageKnifeRequestSource } from '../model/ImageKnifeData'; -import { DownsampleStrategy } from '../downsampling/DownsampleStartegy'; @Sendable export class DefaultEngineKey implements IEngineKey { @@ -32,9 +31,6 @@ export class DefaultEngineKey implements IEngineKey { if (imageKnifeOption.transformation) { key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";" } - if ((imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE && imageKnifeOption.downsampleOf !== undefined)) { - key += "downsampleOf" + imageKnifeOption.downsampleOf +"width="+width+"height="+ height - } } return key } diff --git a/library/src/main/ets/model/ImageKnifeData.ets b/library/src/main/ets/model/ImageKnifeData.ets index 566b6bc..2c7156c 100644 --- a/library/src/main/ets/model/ImageKnifeData.ets +++ b/library/src/main/ets/model/ImageKnifeData.ets @@ -18,7 +18,7 @@ import { IEngineKey } from '../key/IEngineKey' import { PixelMapTransformation } from '../transform/PixelMapTransformation' import common from '@ohos.app.ability.common'; import { Size } from '@kit.ArkUI' -import { DownsampleStrategy } from '../downsampling/DownsampleStartegy' + export interface ImageKnifeData { source: PixelMap | string, imageWidth: number, @@ -103,9 +103,6 @@ export interface RequestJobRequest { fileCacheFolder: string, isAnimator?: boolean, moduleName?:string, - resName?: string, - targetWidth: number - targetHeight: number - downsampType?: DownsampleStrategy + resName?: string }