Compare commits

..

25 Commits
master ... 3.x

Author SHA1 Message Date
tyBrave 1153390393 保持英文README不变
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-29 16:42:32 +08:00
tyBrave 7210d5060b 更新README文件
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-29 16:23:38 +08:00
tyBrave 1c7bedc6d5 同步3.x分支代码
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-29 07:31:35 +00:00
tyBrave 5f2e80400a 更改针对接口回调信息需求的审核意见
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-29 15:17:47 +08:00
zgf fd0394a80a 排队队列改为Queue、showPixelMap回调改为同步
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-28 14:39:40 +08:00
tyBrave c5a861f4fe 更改接口回调信息的README
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-25 22:51:18 +08:00
tyBrave b57194cf4c 新增接口回调信息功能
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-25 22:48:53 +08:00
tyBrave 1a2326c691 新增图片加载回调信息demo及其xts
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-25 22:47:25 +08:00
madixin 9c0b4ebace 1.修复并发相同请求,只收到第一个onLoadStart的bug
2.判断是否要排队的条件,修改为大于等于maxRequests

Signed-off-by: madixin <madixin@huawei.com>
2024-10-25 17:17:44 +08:00
zgf 8d4442157c 子线程网络请求和自定义网络改为异步请求、复用场景清空组件内容
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-25 09:02:32 +00:00
zgf a34e20acfa 子线程网络请求和自定义网络改为异步请求、复用场景清空组件内容
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-25 17:01:18 +08:00
zgf 8dd224e7e6 修改CHANGELOG3.0.3正式版本
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-24 17:48:47 +08:00
tyBrave 7f51e9164e 新增onLoadCancel接口回调的demo
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-21 14:30:33 +08:00
tyBrave 41be71bb73 新增从缓存中获取图片的格式大小等的xts
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-21 14:29:46 +08:00
tyBrave 08b36b7803 新增图片颜色变化demo
Signed-off-by: tyBrave <tianyong21@h-partners.com>
2024-10-21 14:28:53 +08:00
zgf cde07275c3 自定义网络方法增加请求头参数
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-11 17:52:32 +08:00
zgf 43dd3c528c 样例国际化
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-10 16:51:11 +08:00
zgf 4383fa3659 新增preload预加载和cancel取消加载接口,添加prefetch配合preload接口样例
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-10 11:34:57 +08:00
zgf aa2cd9c1bf 新增reload加载接口和网络恢复重新加载样例
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-10-09 15:35:06 +08:00
zgf 1787fffea7 3.x分支xts引入文件报错修改
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-09-30 17:10:07 +08:00
zgf 8e773e929a 3.x分支修改CHANGELOG版本号
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-09-30 16:18:59 +08:00
zgf a3ed45a468 3.x分支更新3.1.0版本代码,并且删除适配componentV2装饰器提交
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-09-30 15:28:02 +08:00
zgf ccd4455b83
!392 修改版本号3.0.2-rc.1
Merge pull request !392 from zgf/3.x
2024-09-29 08:30:37 +00:00
zgf 2fc1f4c776 修改版本号3.0.2-rc.1
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-09-29 16:14:21 +08:00
zgf 6dcf2840b3 FileUtil.readFile接口和file格式图片同步关闭fd
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-09-27 09:58:27 +08:00
106 changed files with 6369 additions and 2037 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "gpu_transform/src/main/cpp/boundscheck/third_party_bounds_checking_function"]
path = gpu_transform/src/main/cpp/boundscheck/third_party_bounds_checking_function
url = https://gitee.com/openharmony/third_party_bounds_checking_function.git

View File

@ -1,27 +1,45 @@
## 3.1.1-rc.1 ## 3.2.0-rc.1
- Photo reduction sampling - Added callback information for image loading
## 3.1.1-rc.0 - Added the interface for obtaining the upper limit and size of the current cache and the number of images corresponding to the current cache
- 重构代码抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中降低函数复杂度 - Change the queue from Stack to Queue
## 3.1.0 - ShowPixelMap callback PixelMap assigns value to Image component to synchronize
## 3.2.0-rc.0
- Rollback the old version V1 decorator. V2 decorator will be provided in version 4.x
- The sub-thread network request is changed to asynchronous, thereby increasing the number of concurrent sub-thread network requests
- Set the concurrency through the setMaxRequests interface under the ImageKnife class
- aboutToRecycle life cycle clear image content
- Fixed bug for receive only the first onLoadStart for concurrent identical requests
- Modify the condition for determining whether to queue to be greater than or equal to maxRequests
## 3.0.3
- Released version 3.0.3
## 3.0.3-rc.0
- Custom network method to add request header parameters
## 3.0.2
- Added new image reloading interface reload
- Added return request preload interface preload
- Added cancel request interface cancel
## 3.0.2-rc.2
- ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件
- 文件缓存数量负数和超过INT最大值时默认为INT最大值
- 修复宽高不等svg图片显示有毛边
- 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别 - 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别
- 修复加载错误图后未去请求排队队列中的请求 - 修复加载错误图后未去请求排队队列中的请求
- 子线程本地Resource参数类型转换成number - 子线程本地Resource参数类型转换成number
- 修改使用hilog记录日志默认打开debug级别的日志 - 修改使用hilog记录日志默认打开debug级别的日志
- file格式图片fd同步close
- 解码pixelMap默认不可编辑图形变化可编辑 - 解码pixelMap默认不可编辑图形变化可编辑
- 修改网络请求超时设置 - 修改网络请求超时设置
- 重构代码抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中降低函数复杂度
## 3.1.0-rc.2 ## 3.0.2-rc.1
- 修复宽高不等svg图片显示有毛边 - release打包关闭混淆
## 3.1.0-rc.1 ## 3.0.2-rc.0
- ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件 - FileUtil.readFile接口和file格式图片同步关闭fd
- 文件缓存数量负数和超过INT最大值时默认为INT最大值
## 3.1.0-rc.0
- ComponentV2装饰器适配
- imageKnifeOption={...}用法改为new ImageKnifeOption({...})
- animatorOption={...}用法改为new AnimatorOption({...})
## 3.0.1 ## 3.0.1
- 修复animatorOption属性设置初始化值失效 - 修复animatorOption属性设置初始化值失效

17
OAT.xml
View File

@ -1,21 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2021 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.
This is the configuration file template for OpenHarmony OSS Audit Tool, please copy it to your project root dir and modify it refer to OpenHarmony/tools_oat/README.
-->
<configuration> <configuration>
<oatconfig> <oatconfig>
<filefilterlist> <filefilterlist>

View File

@ -2,9 +2,9 @@
{ {
"Name": "glide", "Name": "glide",
"License": "Apache License 2.0", "License": "Apache License 2.0",
"License File": "LICENSE", "License File": "https://github.com/bumptech/glide/blob/master/LICENSE",
"Version Number": "4.13.1", "Version Number": "4.13.1",
"Owner" : "xiafeng@huawei.com", "Owner" : "bumptech",
"Upstream URL": "https://github.com/bumptech/glide", "Upstream URL": "https://github.com/bumptech/glide",
"Description": "An image loading and caching library focused on smooth scrolling" "Description": "An image loading and caching library focused on smooth scrolling"
}, },
@ -12,9 +12,9 @@
{ {
"Name": "glide-transformations", "Name": "glide-transformations",
"License": "Apache License 2.0", "License": "Apache License 2.0",
"License File": "LICENSE", "License File": "https://github.com/wasabeef/glide-transformations/blob/main/LICENSE",
"Version Number": "4.3.0", "Version Number": "4.3.0",
"Owner" : "xiafeng@huawei.com", "Owner" : "wasabeef",
"Upstream URL": "https://github.com/wasabeef/glide-transformations", "Upstream URL": "https://github.com/wasabeef/glide-transformations",
"Description": " An transformation library providing a variety of image transformations for Glide. " "Description": " An transformation library providing a variety of image transformations for Glide. "
}, },
@ -22,9 +22,9 @@
{ {
"Name": "fresco", "Name": "fresco",
"License": "MIT License", "License": "MIT License",
"License File": "LICENSE", "License File": "https://github.com/facebook/fresco/blob/main/LICENSE",
"Version Number": "2.6.0", "Version Number": "2.6.0",
"Owner" : "xiafeng@huawei.com", "Owner" : "facebook",
"Upstream URL": "https://github.com/facebook/fresco", "Upstream URL": "https://github.com/facebook/fresco",
"Description": " An library for managing images and the memory they use. " "Description": " An library for managing images and the memory they use. "
}, },
@ -32,9 +32,9 @@
{ {
"Name": "UPNG.js", "Name": "UPNG.js",
"License": "MIT License", "License": "MIT License",
"License File": "LICENSE", "License File": "https://github.com/photopea/UPNG.js/blob/master/LICENSE",
"Version Number": "1.0.0", "Version Number": "1.0.0",
"Owner" : "xiafeng@huawei.com", "Owner" : "photopea",
"Upstream URL": "https://github.com/photopea/UPNG.js", "Upstream URL": "https://github.com/photopea/UPNG.js",
"Description": " Fast and advanced PNG (APNG) decoder and encoder (lossy / lossless) " "Description": " Fast and advanced PNG (APNG) decoder and encoder (lossy / lossless) "
}, },
@ -42,9 +42,9 @@
{ {
"Name": "Luban", "Name": "Luban",
"License": "Apache License 2.0", "License": "Apache License 2.0",
"License File": "LICENSE", "License File": "https://github.com/Curzibn/Luban/blob/master/LICENSE",
"Version Number": "1.1.8", "Version Number": "1.1.8",
"Owner" : " xiafeng@huawei.com", "Owner" : " Curzibn",
"Upstream URL": "https://github.com/Curzibn/Luban", "Upstream URL": "https://github.com/Curzibn/Luban",
"Description": " Luban(鲁班)—Image compression with efficiency very close to WeChat Moments/可能是最接近微信朋友圈的图片压缩算法 " "Description": " Luban(鲁班)—Image compression with efficiency very close to WeChat Moments/可能是最接近微信朋友圈的图片压缩算法 "
}, },
@ -54,16 +54,16 @@
"License": "Apache License 2.0", "License": "Apache License 2.0",
"License File": "https://github.com/Yalantis/uCrop/blob/develop/README.md", "License File": "https://github.com/Yalantis/uCrop/blob/develop/README.md",
"Version Number": "2.2.8", "Version Number": "2.2.8",
"Owner" : " xiafeng@huawei.com", "Owner" : " Yalantis",
"Upstream URL": "https://github.com/Yalantis/uCrop", "Upstream URL": "https://github.com/Yalantis/uCrop",
"Description": " Image Cropping Library " "Description": " Image Cropping Library "
}, },
{ {
"Name": "js-spark-md5", "Name": "js-spark-md5",
"License": "MIT", "License": "MIT",
"License File": "LICENSE", "License File": "https://github.com/satazor/js-spark-md5/blob/master/LICENSE",
"Version Number": "v3.0.2", "Version Number": "v3.0.2",
"Owner" : "xiafeng@huawei.com", "Owner" : "satazor",
"Upstream URL": "https://github.com/satazor/js-spark-md5", "Upstream URL": "https://github.com/satazor/js-spark-md5",
"Description": "Lightning fast normal and incremental md5 for javascript" "Description": "Lightning fast normal and incremental md5 for javascript"
} }

View File

@ -56,12 +56,12 @@ await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption:{
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
@ -69,12 +69,12 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: this.localFile, loadSrc: this.localFile,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
@ -82,12 +82,12 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
@ -95,13 +95,13 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg", loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto, objectFit: ImageFit.Auto,
customGetImage: custom customGetImage: custom
}) }
}).width(100).height(100) }).width(100).height(100)
// Custom implementation of the image acquisition method, such as custom network download。 // Custom implementation of the image acquisition method, such as custom network download。
@ -117,33 +117,33 @@ async function custom(context: Context, src: string | PixelMap | Resource): Prom
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)} progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)}
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 6. Setting Border Options #### 6. Setting Border Options
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
border: {radius:50} border: {radius:50}
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 7. Setting Image Transformation Options #### 7. Setting Image Transformation Options
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
border: {radius:50}, border: {radius:50},
transformation: new BlurTransformation(3) transformation: new BlurTransformation(3)
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
Multiple combined transformation usages: Multiple combined transformation usages:
@ -153,14 +153,14 @@ let transformations: collections.Array<PixelMapTransformation> = new collections
transformations.push(new BlurTransformation(5)); transformations.push(new BlurTransformation(5));
transformations.push(new BrightnessTransformation(0.2)); transformations.push(new BrightnessTransformation(0.2));
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: { topLeft: 50, bottomRight: 50 } }, // Rounded corner settings border: { radius: { topLeft: 50, bottomRight: 50 } }, // Rounded corner settings
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // Graphic transformation group transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // Graphic transformation group
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.rotate ({angle: 90}) // Rotate by 90 degrees. .rotate ({angle: 90}) // Rotate by 90 degrees.
@ -171,12 +171,12 @@ Other transformation-related properties can be stacked to achieve combined trans
Example of circular cropping transformation: Example of circular cropping transformation:
``` ```
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Cover, objectFit: ImageFit.Cover,
border: { radius: 150 } border: { radius: 150 }
}) }
}).width(300) }).width(300)
.height(300) .height(300)
``` ```
@ -184,12 +184,12 @@ ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
Example of Circular cropping with border transformation: Example of Circular cropping with border transformation:
``` ```
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Cover, objectFit: ImageFit.Cover,
border: { radius: 150, color: Color.Red, width: 5 } border: { radius: 150, color: Color.Red, width: 5 }
}) }
}).width(300) }).width(300)
.height(300) .height(300)
``` ```
@ -198,9 +198,9 @@ Example of contrast filtering transformation:
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample') loadSrc: $r('app.media.pngSample')
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.contrast(12) .contrast(12)
@ -210,9 +210,9 @@ Example of rotation transformation:
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption:({
loadSrc: $r('app.media.pngSample') loadSrc: $r('app.media.pngSample')
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.rotate({angle:90}) .rotate({angle:90})
@ -222,7 +222,7 @@ ImageKnifeComponent({
#### 8. Listening for Image Loading Success and Failure #### 8. Listening for Image Loading Success and Failure
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
onLoadListener:{ onLoadListener:{
@ -241,40 +241,29 @@ ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
console.info(err) console.info(err)
} }
} }
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 9. Use of syncLoad #### 9. Use of syncLoad
**syncLoad** sets whether to load the image synchronously. By default, the image is loaded asynchronously. When loading a small image, you are advised to set **syncLoad** to **true** so that the image loading can be quickly completed on the main thread. **syncLoad** sets whether to load the image synchronously. By default, the image is loaded asynchronously. When loading a small image, you are advised to set **syncLoad** to **true** so that the image loading can be quickly completed on the main thread.
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.pngSample"), loadSrc:$r("app.media.pngSample"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
``` ```
#### 10. Use of ImageKnifeAnimatorComponent #### 10. Use of ImageKnifeAnimatorComponent
``` ```
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption },animatorOption:this.animatorOption
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) }).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)
```
#### Reuse Scenario #### Reuse Scenario
Clear the component content in the **aboutToRecycle** lifecycle and trigger image loading through watch observeration. Clear the component content in the **aboutToRecycle** lifecycle and trigger image loading through watch observeration.
## Available APIs ## Available APIs
@ -319,17 +308,7 @@ Clear the component content in the **aboutToRecycle** lifecycle and trigger imag
| drawingColorFilter | ColorFilter | Drawing color filter. Optional. | | drawingColorFilter | ColorFilter | Drawing color filter. Optional. |
| onComplete | (event:EventImage \| undefined)=>void | Callback for image loading completion. Optional. | | onComplete | (event:EventImage \| undefined)=>void | Callback for image loading completion. Optional. |
| onLoadListener | onLoadStart:()=>void,onLoadSuccess:(data:string\|Pixelmap)=>void | Callback for image loading events. Optional. | | onLoadListener | onLoadStart:()=>void,onLoadSuccess:(data:string\|Pixelmap)=>void | Callback for image loading events. Optional. |
| downsampleOf | DownsampleStrategy | 降采样(可选) |
### 降采样类型
| 类型 | 相关描述 |
|---------------------|-------------------|
| NONE | 不进行降采样 |
| AT_MOST | 请求尺寸大于实际尺寸不进行放大 |
| FIT_CENTER_MEMORY | 两边自适应内存优先 |
| FIT_CENTER_QUALITY | 两边自适应质量优先 |
| CENTER_OUTSIDE_MEMORY | 宽高缩放比最大的比例,进行缩放适配内存优先 |
| CENTER_OUTSIDE_QUALITY | 宽高缩放比最大的比例,进行缩放适配质量优先 |
| AT_LEAST | 根据宽高的最小的比例,进行适配 |
### ImageKnife ### ImageKnife
| Parameter | Type | Description | | Parameter | Type | Description |
@ -380,7 +359,7 @@ Method 2: Set the third-party HAR as a dependency in the **oh-package.json5** fi
This project has been verified in the following version: This project has been verified in the following version:
DevEco Studio: 5.0 Canary3 (5.0.3.502), SDK: API 12 (5.0.0.31) DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)
## How to Contribute ## How to Contribute
@ -393,4 +372,4 @@ This project is licensed under [Apache License 2.0](https://gitee.com/openharmon
## Known Issues ## Known Issues
- The **ImageFit** attribute cannot be set for the **ImageKnifeAnimator** component. - The **ImageFit** attribute cannot be set for the **ImageKnifeAnimator** component.
- The **border** attribute of the **ImageKnifeAnimator** component cannot make the image rounded corners. - The **border** attribute of the **ImageKnifeAnimator** component cannot make the image rounded corners.

View File

@ -56,12 +56,12 @@ await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
@ -69,12 +69,12 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: this.localFile, loadSrc: this.localFile,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
@ -82,12 +82,12 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
@ -95,13 +95,13 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg", loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto, objectFit: ImageFit.Auto,
customGetImage: custom customGetImage: custom
}) }
}).width(100).height(100) }).width(100).height(100)
// 自定义实现图片获取方法,如自定义网络下载 // 自定义实现图片获取方法,如自定义网络下载
@ -117,33 +117,33 @@ async function custom(context: Context, src: string | PixelMap | Resource): Prom
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)} progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)}
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 6.支持option传入border设置边框圆角 #### 6.支持option传入border设置边框圆角
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
border: {radius:50} border: {radius:50}
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 7.支持option图片变换 #### 7.支持option图片变换
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
border: {radius:50}, border: {radius:50},
transformation: new BlurTransformation(3) transformation: new BlurTransformation(3)
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
多种组合变换用法 多种组合变换用法
@ -153,14 +153,14 @@ let transformations: collections.Array<PixelMapTransformation> = new collections
transformations.push(new BlurTransformation(5)); transformations.push(new BlurTransformation(5));
transformations.push(new BrightnessTransformation(0.2)); transformations.push(new BrightnessTransformation(0.2));
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: { topLeft: 50, bottomRight: 50 } }, // 圆角设置 border: { radius: { topLeft: 50, bottomRight: 50 } }, // 圆角设置
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // 图形变换组 transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // 图形变换组
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.rotate({ angle: 90 }) // 旋转90度 .rotate({ angle: 90 }) // 旋转90度
@ -171,12 +171,12 @@ ImageKnifeComponent({
圆形裁剪变换示例 圆形裁剪变换示例
``` ```
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Cover, objectFit: ImageFit.Cover,
border: { radius: 150 } border: { radius: 150 }
}) }
}).width(300) }).width(300)
.height(300) .height(300)
``` ```
@ -184,12 +184,12 @@ ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
圆形裁剪带边框变换示例 圆形裁剪带边框变换示例
``` ```
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Cover, objectFit: ImageFit.Cover,
border: { radius: 150, color: Color.Red, width: 5 } border: { radius: 150, color: Color.Red, width: 5 }
}) }
}).width(300) }).width(300)
.height(300) .height(300)
``` ```
@ -198,9 +198,9 @@ ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample') loadSrc: $r('app.media.pngSample')
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.contrast(12) .contrast(12)
@ -210,9 +210,9 @@ ImageKnifeComponent({
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample') loadSrc: $r('app.media.pngSample')
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.rotate({angle:90}) .rotate({angle:90})
@ -222,7 +222,7 @@ ImageKnifeComponent({
#### 8.监听图片加载成功与失败 #### 8.监听图片加载成功与失败
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
onLoadListener:{ onLoadListener:{
@ -241,29 +241,60 @@ ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
console.info(err) console.info(err)
} }
} }
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 9.ImageKnifeComponent - syncLoad #### 9.ImageKnifeComponent - syncLoad
设置是否同步加载图片默认是异步加载。建议加载尺寸较小的Resource图片时将syncLoad设为true因为耗时较短在主线程上执行即可 设置是否同步加载图片默认是异步加载。建议加载尺寸较小的Resource图片时将syncLoad设为true因为耗时较短在主线程上执行即可
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.pngSample"), loadSrc:$r("app.media.pngSample"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
``` ```
#### 10.ImageKnifeAnimatorComponent 示例 #### 10.ImageKnifeAnimatorComponent 示例
``` ```
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption: {
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption },animatorOption:this.animatorOption
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
``` ```
#### 11.加载图片回调信息数据 示例
```
ImageKnifeComponent({ ImageKnifeOption: = new ImageKnifeOption({
loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (req) => {
let startCallBackData = JSON.stringify(req?.getImageKnifeData());
},
onLoadFailed: (res, req) => {
let failedBackData = res + ";" + JSON.stringify(req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
let successBackData = JSON.stringify(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
let cancelBackData = res + ";" + JSON.stringify(req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
let render_success = JSON.stringify(Date.now())
}
}
})
}).width(100).height(100)
```
#### 复用场景 #### 复用场景
在aboutToRecycle生命周期清空组件内容通过watch监听触发图片的加载。 在aboutToRecycle生命周期清空组件内容通过watch监听触发图片的加载。
## 接口说明 ## 接口说明
@ -287,44 +318,60 @@ ImageKnifeAnimatorComponent({
### ImageKnifeOption参数列表 ### ImageKnifeOption参数列表
| 参数名称 | 入参内容 | 功能简介 | | 参数名称 | 入参内容 | 功能简介 |
|-----------------------|-------------------------------------------------------|-----------------| |-----------------------|---------------------------------------------------------------------------------------------------------------------------------------|---------------|
| loadSrc | string、PixelMap、Resource | 主图展示 | | loadSrc | string、PixelMap、Resource | 主图展示 |
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) | | placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) | | errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
| objectFit | ImageFit | 主图填充效果(可选) | | objectFit | ImageFit | 主图填充效果(可选) |
| placeholderObjectFit | ImageFit | 占位图填充效果(可选) | | placeholderObjectFit | ImageFit | 占位图填充效果(可选) |
| errorholderObjectFit | ImageFit | 错误图填充效果(可选) | | errorholderObjectFit | ImageFit | 错误图填充效果(可选) |
| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) | | writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) |
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) | | onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 | | customGetImage | customGetImage?:(context: Context, src: string、PixelMap、Resource ,headers?: Record<string, Object>) => Promise<ArrayBufferundefined> | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
| border | BorderOptions | 边框圆角(可选) | | border | BorderOptions | 边框圆角(可选) |
| priority | taskpool.Priority | 加载优先级(可选) | | priority | taskpool.Priority | 加载优先级(可选) |
| context | common.UIAbilityContext | 上下文(可选) | | context | common.UIAbilityContext | 上下文(可选) |
| progressListener | (progress: number)=>void | 进度(可选) | | progressListener | (progress: number)=>void | 进度(可选) |
| signature | String | 自定义缓存关键字(可选) | | signature | String | 自定义缓存关键字(可选) |
| headerOption | Array<HeaderOptions> | 设置请求头(可选) | | headerOption | Array<HeaderOptions> | 设置请求头(可选) |
| transformation | PixelMapTransformation | 图片变换(可选) | | transformation | PixelMapTransformation | 图片变换(可选) |
| drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) | | drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) |
| onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) | | onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) |
| onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 | | onLoadListener | onLoadStart?: (req?: ImageKnifeRequest) => void,onLoadSuccess?: (data: string \| PixelMap \| undefined, imageData: ImageKnifeData, req?: ImageKnifeRequest) => void,onLoadFailed?: (err: string, req?: ImageKnifeRequest) => void,onLoadCancel?: (res: string, req?: ImageKnifeRequest) => void | 监听图片加载成功与失败 |
### ImageKnife接口 ### ImageKnife接口
| 参数名称 | 入参内容 | 功能简介 | | 参数名称 | 入参内容 | 功能简介 |
|------------------|-------------------------------------------------------------------------------------------------------|---------------| |-------------------|-------------------------------------------------------------------------------------------------------|------------------|
| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 | | initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 |
| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | | initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 |
| preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 | | reload | request: ImageKnifeRequest | 图片重新加载 |
| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 | | preLoad | loadSrc: string I ImageKnifeOption | 预加载返回图片请求request |
| addHeader | key: string, value: Object | 全局添加http请求头 | | cancel | request: ImageKnifeRequest | 取消图片请求 |
| setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 | | preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 |
| deleteHeader | key: string | 全局删除http请求头 | | getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 |
| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined> | 全局设置自定义下载 | | addHeader | key: string, value: Object | 全局添加http请求头 |
| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | | setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 |
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | | deleteHeader | key: string | 全局删除http请求头 |
| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 | | setCustomGetImage | customGetImage?: (context: Context, src: string、PixelMap、Resource ,headers?: Record<string, Object>) => Promise<ArrayBufferundefined> | PixelMap | Resource) => Promise<ArrayBuffer | undefined> | 全局设置自定义下载 |
| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 | | setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 |
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 |
| removeMemoryCache | url: string | ImageKnifeOption | 清理指定内存缓存 |
| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 |
| getCacheLimitSize | cacheType?: CacheStrategy | 获取指定缓存的上限大小 |
| getCurrentCacheNum | cacheType?: CacheStrategy | 获取指定缓存的当前缓存图片个数 |
| getCurrentCacheSize | cacheType?: CacheStrategy | 获取指定缓存的当前大小 |
| getCurrentCacheSize | cacheType?: CacheStrategy | 获取指定缓存的当前大小 |
### 回调接口说明
| 回调接口 | 回调字段 | 回调描述 |
|----------------|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| onLoadStart | req: ImageKnifeRequest | req返回字段中包含了图片请求的信息如图片的url及其组件的宽高同时ImageKnifeRequest包含了ImageKnifeData其中包含此次请求的开始及其检查内存缓存的时间点 |
| onLoadSuccess | data: string \| PixelMap \| undefined, imageData: ImageKnifeData, req?: ImageKnifeRequest | data:加载成功的结果数据imageData图片的存入缓存中的信息 req图片请求的信息同时其中的ImageKnifeData包含此次请求中图片的原始大小、图片的解码大小、格式、图片帧、请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束等时间点 |
| onLoadFailed | err: string, req?: ImageKnifeRequest | err:错误信息描述req图片请求的信息同时其中的ImageKnifeData包含此次请求错误信息ErrorInfoTimeInfoErrorInfo其中包含了错误阶段、错误码及其网络请求的错误码TimeInfo中包含请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束等时间点 |
| onLoadCancel | reason: string, req?: ImageKnifeRequest | reason:取消回调原因req图片请求的信息同时其中的ImageKnifeData包含此次请求错误信息ErrorInfoTimeInfoErrorInfo其中包含了错误阶段、错误码及其网络请求的错误码TimeInfo中包含请求结束时间、磁盘检查时间、网络请求开始结束、图片解码开始结束及其请求取消等时间点 |
### 图形变换类型需要为GPUImage添加依赖项 ### 图形变换类型需要为GPUImage添加依赖项
| 类型 | 相关描述 | | 类型 | 相关描述 |
@ -358,7 +405,7 @@ ImageKnifeAnimatorComponent({
## 约束与限制 ## 约束与限制
在下述版本验证通过: 在下述版本验证通过:
DevEco Studio 5.0 Canary35.0.3.502--SDK:API12 (5.0.0.31) DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)
## 贡献代码 ## 贡献代码

View File

@ -7,8 +7,9 @@
{ {
"name": "default", "name": "default",
"signingConfig": "default", "signingConfig": "default",
"compileSdkVersion": 12, "compileSdkVersion": "5.0.0(12)",
"compatibleSdkVersion": 12 "compatibleSdkVersion": "5.0.0(12)",
"runtimeOS": "HarmonyOS",
} }
], ],
"buildModeSet": [ "buildModeSet": [
@ -37,10 +38,6 @@
"name": "library", "name": "library",
"srcPath": "./library" "srcPath": "./library"
}, },
{
"name": "gpu_transform",
"srcPath": "./gpu_transform"
},
{ {
"name": "sharedlibrary", "name": "sharedlibrary",
"srcPath": "./sharedlibrary", "srcPath": "./sharedlibrary",

View File

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { DownsampleStrategy } from '@ohos/imageknife';
import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource} from '@ohos/libraryimageknife'; import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource} from '@ohos/libraryimageknife';
//全局自定义key demo //全局自定义key demo
@ -36,9 +35,6 @@ export class CustomEngineKeyImpl implements IEngineKey {
if (imageKnifeOption.transformation) { if (imageKnifeOption.transformation) {
key += "transformation=" + this.getTransformation(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 return key
} }

View File

@ -17,7 +17,7 @@ import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility'; import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want'; import Want from '@ohos.app.ability.Want';
import window from '@ohos.window'; import window from '@ohos.window';
import { ImageKnife, InitImageKnife, LogUtil } from '@ohos/libraryimageknife'; import { ImageKnife, InitImageKnife } from '@ohos/libraryimageknife';
import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl'; import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl';
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import { BusinessError } from '@ohos.base' import { BusinessError } from '@ohos.base'

View File

@ -0,0 +1,78 @@
/*
* 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 { InfoItem } from './model/DataSourcePrefetching';
import { PageViewModel } from './model/PageViewModel';
import { ImageKnifeComponent, ImageKnife } from '@ohos/libraryimageknife';
import { CommonDataSource, GetSession } from './model/CommonDataSource';
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
export struct CustomNetImagePage {
@State hotCommendList:CommonDataSource<InfoItem> = new CommonDataSource<InfoItem>([])
aboutToAppear(): void {
ImageKnife.getInstance().setMaxRequests(32)
this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems())
}
aboutToDisappear(): void {
ImageKnife.getInstance().setMaxRequests(8)
}
build() {
Column() {
WaterFlow() {
LazyForEach(this.hotCommendList,(item: InfoItem)=>{
FlowItem() {
Column(){
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: item.albumUrl,
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"),
customGetImage:custom
}
}).width("50%").height(200)
}
}.height(200)
.backgroundColor("#95efd2")
},(item: string) => item)
}.columnsTemplate("1fr 1fr")
.columnsGap(10)
.rowsGap(5)
.backgroundColor(0xFAEEE0)
.width("100%").height("100%")
}
}
}
// 自定义下载方法
@Concurrent
async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>): Promise<ArrayBuffer | undefined> {
return new Promise((resolve,reject)=>{
if (typeof src == "string") {
let session = GetSession.session
let req = new rcp.Request(src,"GET");
session.fetch(req).then((response)=>{
if(response.statusCode == 200) {
let buffer = response.body
resolve(buffer)
} else {
reject("rcp code:"+response.statusCode)
}
}).catch((err:BusinessError)=>{
reject("error rcp src:"+src+",err:"+JSON.stringify(err))
})
}
})
}

View File

@ -1,214 +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 } 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(7, "AT_LEAST"),
new SamplingType(1, "AT_MOST"),
new SamplingType(2, "FIT_CENTER_MEMORY"),
new SamplingType(4, "FIT_CENTER_QUALITY"),
new SamplingType(5, "CENTER_OUTSIDE_MEMORY"),
new SamplingType(6, "CENTER_OUTSIDE_QUALITY"),
new SamplingType(0, "NONE"),
]
@Local checked: boolean = false
updateImageKnifeOption(value: string) {
if (value === 'NONE') {
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.NONE
})
this.originalPixMap($r('app.media.pngSample'))
this.afterSamplingFunc($r('app.media.pngSample'))
} else if (value === 'AT_MOST') {
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.AT_MOST
})
this.originalPixMap($r('app.media.pngSample'))
this.afterSamplingFunc($r('app.media.pngSample'))
} 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_OUTSIDE_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.CENTER_OUTSIDE_MEMORY
})
this.originalPixMap($r('app.media.pngSample'))
this.afterSamplingFunc($r('app.media.pngSample'))
} else if (value === 'CENTER_OUTSIDE_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.CENTER_OUTSIDE_QUALITY
})
this.originalPixMap($r('app.media.pngSample'))
this.afterSamplingFunc($r('app.media.pngSample'))
} else {
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.AT_LEAST
})
this.originalPixMap($r('app.media.pngSample'))
this.afterSamplingFunc($r('app.media.pngSample'))
}
}
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)) as string;
let decodingOptions: image.DecodingOptions = {
editable: true,
desiredPixelFormat: 3,
}
let imageInfo = await imageSource.getImageInfo()
if (this.imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE){
let reqSize =
new Downsampler().calculateScaling(typeValue, imageInfo.size.width, imageInfo.size.height, 300,
300, this.imageKnifeOption.downsampleOf)
decodingOptions = {
editable: true,
desiredSize: {
width: reqSize.width,
height: reqSize.height
}
}
}
// 创建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")
});
}
getResourceString(res:Resource){
return getContext().resourceManager.getStringSync(res.id)
}
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(this.getResourceString($r('app.string.Sampling_pecification'))+ item.value).fontSize(20)
}
}, (item: SamplingType) => JSON.stringify(item))
Column() {
Text(`${this.getResourceString($r('app.string.Unreal_samples'))}${this.beforeSampling}`).fontSize(20)
Text(`${ this.getResourceString($r('app.string.After_the_sampling'))}${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
}
}

View File

@ -12,14 +12,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { AnimatorOption, ImageKnifeAnimatorComponent,ImageKnifeOption } from "@ohos/libraryimageknife" import { AnimatorOption, ImageKnifeAnimatorComponent } from "@ohos/libraryimageknife"
@Entry @Entry
@ComponentV2 @Component
struct ImageAnimatorPage { struct ImageAnimatorPage {
@Local animatorOption: AnimatorOption = new AnimatorOption({ @State animatorOption: AnimatorOption = {
state: AnimationStatus.Running, state: AnimationStatus.Running,
iterations: -1, iterations: 1,
onFinish:()=>{ onFinish:()=>{
console.log("ImageKnifeAnimatorComponent animatorOption onFinish") console.log("ImageKnifeAnimatorComponent animatorOption onFinish")
}, },
@ -35,14 +35,14 @@ struct ImageAnimatorPage {
onRepeat:()=>{ onRepeat:()=>{
console.log("ImageKnifeAnimatorComponent animatorOption onRepeat") console.log("ImageKnifeAnimatorComponent animatorOption onRepeat")
} }
}) }
@Local animatorOption1: AnimatorOption = new AnimatorOption({ @State animatorOption1: AnimatorOption = {
state: AnimationStatus.Initial state: AnimationStatus.Initial
}) }
@Local animatorOption2: AnimatorOption = new AnimatorOption({ @State animatorOption2: AnimatorOption = {
state: AnimationStatus.Initial, state: AnimationStatus.Initial,
reverse: true reverse: true
}) }
build() { build() {
Column(){ Column(){
Flex(){ Flex(){
@ -66,27 +66,27 @@ struct ImageAnimatorPage {
}) })
} }
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption },animatorOption:this.animatorOption
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
Text($r('app.string.Display_the_first_frame')).fontSize(20) Text($r('app.string.Display_the_first_frame')).fontSize(20)
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption1 },animatorOption:this.animatorOption1
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) }).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
Text($r('app.string.Display_the_last_frame')).fontSize(20) Text($r('app.string.Display_the_last_frame')).fontSize(20)
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption2 },animatorOption:this.animatorOption2
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) }).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
}.width("100%").height("100%") }.width("100%").height("100%")
} }

View File

@ -0,0 +1,82 @@
/*
* 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 { connection } from '@kit.NetworkKit'
import { List } from '@kit.ArkTS'
import { ImageKnifeRequest,ImageKnife,ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry
@Component
struct ImageKnifeReload {
aboutToAppear(): void {
NetWatchState.init()
}
build() {
Column() {
ImageKnifeComponent({
imageKnifeOption:{
loadSrc:"https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp",
placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'),
onLoadListener:{
onLoadFailed(err,request){
NetWatchState.requestList.add(request)
}
}
}
}).width(200).height(200)
ImageKnifeComponent({
imageKnifeOption:{
loadSrc:"https://img-blog.csdn.net/20140514114029140",
placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'),
onLoadListener:{
onLoadFailed(err,request){
NetWatchState.requestList.add(request)
}
}
}
}).width(200).height(200).margin({top:10})
}.width("100%")
.height("100%")
}
}
class NetWatchState {
public static netConnection: connection.NetConnection | undefined = undefined
public static requestList: List<ImageKnifeRequest> = new List()
static init() {
NetWatchState.netConnection = connection.createNetConnection()
// 注册订阅事件
NetWatchState.netConnection.register(()=>{
})
// 订阅网络能力变化事件。调用register后才能接收到此事件通知
NetWatchState.netConnection.on("netCapabilitiesChange",(data:connection.NetCapabilityInfo)=>{
if(NetWatchState.requestList.length > 0 && data.netHandle.netId >= 100) {
NetWatchState.requestList.forEach((request)=>{
ImageKnife.getInstance().reload(request)
NetWatchState.requestList.remove(request)
})
}
})
}
static cancel(){
if(NetWatchState.netConnection != undefined) {
// 取消订阅
NetWatchState.netConnection.unregister(()=>{})
}
}
}

View File

@ -35,17 +35,17 @@ import {
import { collections } from '@kit.ArkTS' import { collections } from '@kit.ArkTS'
@Entry @Entry
@ComponentV2 @Component
struct ImageTransformation { struct ImageTransformation {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain objectFit: ImageFit.Contain
}) }
@Local isRound: boolean = false; @State isRound: boolean = false;
@Local isContrast: boolean = false; @State isContrast: boolean = false;
@Local isRotate: boolean = false; @State isRotate: boolean = false;
isBlur: boolean = false isBlur: boolean = false
isBrightness: boolean = false isBrightness: boolean = false
isGrayScale: boolean = false; isGrayScale: boolean = false;
@ -412,14 +412,14 @@ struct ImageTransformation {
if (this.isMask) { if (this.isMask) {
transformations.push(new MaskTransformation($r('app.media.mask_starfish'))); transformations.push(new MaskTransformation($r('app.media.mask_starfish')));
} }
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: this.isRound ? { topLeft: 50, bottomRight: 50 } : 0 }, border: { radius: this.isRound ? { topLeft: 50, bottomRight: 50 } : 0 },
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined
}) }
if (this.isCropCircle) { if (this.isCropCircle) {
this.imageKnifeOption.objectFit = ImageFit.Cover; this.imageKnifeOption.objectFit = ImageFit.Cover;
this.imageKnifeOption.border = { radius: 150 }; this.imageKnifeOption.border = { radius: 150 };

View File

@ -15,153 +15,171 @@
import router from '@system.router'; import router from '@system.router';
@Entry @Entry
@ComponentV2 @Component
struct Index { struct Index {
getResourceString(res: Resource) {
getResourceString(res:Resource){
return getContext().resourceManager.getStringSync(res.id) return getContext().resourceManager.getStringSync(res.id)
} }
aboutToAppear(): void { aboutToAppear(): void {
} }
build() { build() {
Scroll() { Scroll(){
Column() { Column() {
Button($r('app.string.Test_ImageAnimator')).onClick(() => { Button($r('app.string.Test_ImageAnimator')).onClick(()=>{
router.push({ router.push({
uri: 'pages/ImageAnimatorPage', uri: 'pages/ImageAnimatorPage',
}); });
}) })
Button($r('app.string.Test_multiple_images')).margin({ top: 10 }).onClick(() => { Button($r('app.string.Network_reload')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/ImageKnifeReload',
});
})
Button($r('app.string.preloading_prefetch')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/PrefetchAndCacheCount',
});
})
Button($r('app.string.request_concurrency')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/SetMaxRequestPage',
});
})
Button($r('app.string.Test_multiple_images')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/TestCommonImage', uri: 'pages/TestCommonImage',
}); });
}) })
Button(this.getResourceString($r('app.string.Multiple_images')) + " + reuse + LazyForeach") Button($r('app.string.Customize_RCP_network')).margin({top:10}).onClick(()=>{
.margin({ top: 10 }) router.push({
.onClick(() => { uri: 'pages/CustomNetImagePage',
router.push({ });
uri: 'pages/UserPage', })
Button($r('app.string.Test_Task_error')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestTaskResourcePage',
});
})
Button($r('app.string.Test_HSP')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestHspPreLoadImage',
}); });
}) })
Button($r('app.string.Test_SingleImage')).margin({ top: 10 }).onClick(() => { Button($r('app.string.Test_SingleImage')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/SingleImage', uri: 'pages/SingleImage',
}); });
}) })
Button($r('app.string.Image_Downsampling_Functionality')).margin({top:10}).onClick(()=>{ Button($r('app.string.Test_custom_download')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/DownSamplePage', uri: 'pages/TestSetCustomImagePage',
}); });
}) })
Button($r('app.string.Display_long_image')).margin({ top: 10 }).onClick(() => { // Button(this.getResourceString($r('app.string.Multiple_images')) + " + LazyForEach").margin({top:10}).onClick(()=>{
// router.push({
// uri: 'pages/ManyPhotoShowPage',
//
// });
// })
Button(this.getResourceString($r('app.string.Multiple_images')) + " + reuse + LazyForeach").margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/UserPage',
});
})
Button($r('app.string.Display_long_image')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/LongImagePage', uri: 'pages/LongImagePage',
}); });
}) })
Button($r('app.string.Image_Transformation')).margin({ top: 10 }).onClick(() => { Button($r('app.string.Image_scaling')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TransformPage',
});
})
Button(this.getResourceString($r('app.string.Message_list')) + " + List").margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestImageFlash',
});
})
Button($r('app.string.Custom_cache_key')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/SignatureTestPage',
});
})
Button($r('app.string.Preloading_images_to_cache')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestPrefetchToFileCache',
});
})
Button($r('app.string.Retrieve_image_display_from_cache')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestIsUrlExist',
});
})
Button($r('app.string.Test_single_request_header')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestHeader',
});
})
Button($r('app.string.Test_write_cache_strategy')).margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestWriteCacheStage',
});
})
Button($r('app.string.Image_Transformation')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/ImageTransformation', uri: 'pages/ImageTransformation',
}); });
}) })
Button($r('app.string.Test_media_URL')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/dataShareUriLoadPage',
}); Button($r('app.string.Different_ObjectFit')).margin({top:10}).onClick(()=>{
})
Button($r('app.string.Different_ObjectFit')).margin({ top: 10 }).onClick(() => {
router.push({ router.push({
uri: 'pages/ObjectFitPage', uri: 'pages/ObjectFitPage',
}); });
}) })
Button($r('app.string.Custom_cache_key')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/SignatureTestPage',
}); Button($r('app.string.Test_image_loading_success_or_failure_events')).margin({top:10}).onClick(()=>{
})
Button($r('app.string.Test_image_loading_success_or_failure_events')).margin({ top: 10 }).onClick(() => {
router.push({ router.push({
uri: 'pages/LoadStatePage', uri: 'pages/LoadStatePage',
}) })
}) })
Button($r('app.string.Image_scaling')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TransformPage',
}); Button($r('app.string.Test_removing_image_cache_interface')).margin({top:10}).onClick(()=>{
})
Button($r('app.string.Test_HSP')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestHspPreLoadImage',
});
})
Button($r('app.string.Test_custom_download')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestSetCustomImagePage',
});
})
Button(this.getResourceString($r('app.string.Message_list')) + " + List").margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestImageFlash',
});
})
Button($r('app.string.Preloading_images_to_cache')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestPrefetchToFileCache',
});
})
Button($r('app.string.Retrieve_image_display_from_cache')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestIsUrlExist',
});
})
Button($r('app.string.Test_single_request_header')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestHeader',
});
})
Button($r('app.string.Test_write_cache_strategy')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestWriteCacheStage',
});
})
Button($r('app.string.Test_removing_image_cache_interface')).margin({ top: 10 }).onClick(() => {
router.push({ router.push({
uri: 'pages/TestRemoveCache', uri: 'pages/TestRemoveCache',
}); });
}) })
Button($r('app.string.Test_error_image_display')).margin({ top: 10 }).onClick(() => { Button($r('app.string.Test_error_image_display')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/TestErrorHolderPage', uri: 'pages/TestErrorHolderPage',
}); });
}) })
Button($r('app.string.Test_Task_error')).margin({ top: 10 }).onClick(() => { Button($r('app.string.Test_media_URL')).margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/TestTaskResourcePage', uri: 'pages/dataShareUriLoadPage',
}); });
}) })
Button($r('app.string.test_cache_btn')).margin({ top: 10 }).onClick(() => { Button($r('app.string.test_cache_btn')).margin({ top: 10 }).onClick(() => {
@ -179,8 +197,14 @@ struct Index {
uri: 'pages/TestLoadCancelListenerPage', uri: 'pages/TestLoadCancelListenerPage',
}); });
}) })
Button($r('app.string.test_callback')).margin({ top: 10 }).onClick(() => {
router.push({
uri: 'pages/TestImageKnifeCallbackPage',
});
})
} }
}.width('100%') } .width('100%')
.height('100%') .height('100%')
} }
} }

View File

@ -0,0 +1,51 @@
/*
* 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 { InfoItem } from './model/DataSourcePrefetching';
import { PageViewModel } from './model/PageViewModel';
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
import { CommonDataSource } from './model/CommonDataSource';
@Entry
@Component
export struct LazyForEachCache {
@State hotCommendList:CommonDataSource<InfoItem> = new CommonDataSource<InfoItem>([])
aboutToAppear(): void {
this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems())
}
build() {
Column() {
List({ space: 16 }) {
LazyForEach(this.hotCommendList, (item: InfoItem,index) => {
ListItem() {
Column({ space: 12 }) {
ImageKnifeComponent({
imageKnifeOption:{
loadSrc: item.albumUrl,
placeholderSrc:$r('app.media.loading')
}
}).width(100).height(100)
Text(`${index}`)
}.border({ width: 5 , color: "#000000"})
}
})
}
.cachedCount(5)
.width("100%")
.height("100%")
.margin({ left: 10, right: 10 })
.layoutWeight(1)
}
}
}

View File

@ -0,0 +1,51 @@
/*
* 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 { InfoItem } from './model/DataSourcePrefetching';
import { PageViewModel } from './model/PageViewModel';
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
import { CommonDataSource } from './model/CommonDataSource';
@Entry
@Component
export struct LazyForEachCount {
@State hotCommendList:CommonDataSource<InfoItem> = new CommonDataSource<InfoItem>([])
aboutToAppear(): void {
this.hotCommendList.addData(this.hotCommendList.totalCount(),PageViewModel.getItems())
}
build() {
Column() {
List({ space: 16 }) {
LazyForEach(this.hotCommendList, (item: InfoItem,index) => {
ListItem() {
Column({ space: 12 }) {
ImageKnifeComponent({
imageKnifeOption:{
loadSrc: item.albumUrl,
placeholderSrc:$r('app.media.loading')
}
}).width(100).height(100)
Text(`${index}`)
}.border({ width: 5 , color: "#000000"})
}
})
}
.cachedCount(30)
.width("100%")
.height("100%")
.margin({ left: 10, right: 10 })
.layoutWeight(1)
}
}
}

View File

@ -15,11 +15,11 @@
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct ListPage { struct ListPage {
private data: string[] = [] private data: string[] = []
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ loadSrc: $r('app.media.startIcon')}) @State ImageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon')}
aboutToAppear(): void { aboutToAppear(): void {

View File

@ -16,12 +16,12 @@ import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife"
import matrix4 from '@ohos.matrix4' import matrix4 from '@ohos.matrix4'
@Entry @Entry
@ComponentV2 @Component
struct LoadStatePage { struct LoadStatePage {
starTime:number = new Date().getTime() starTime:number = new Date().getTime()
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State ImageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
@ -35,14 +35,14 @@ struct LoadStatePage {
}, },
}, },
border: { radius: 50 } border: { radius: 50 }
}) }
@Local imageKnifeOption1: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption1: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon') loadSrc: $r('app.media.startIcon')
}) }
@Local message: string = "" @State message: string = ""
@Local currentWidth: number = 200 @State currentWidth: number = 200
@Local currentHeight: number = 200 @State currentHeight: number = 200
@Local typeValue: string = "" @State typeValue: string = ""
build() { build() {
Column() { Column() {
Text($r('app.string.TIPS')) Text($r('app.string.TIPS'))
@ -50,7 +50,7 @@ struct LoadStatePage {
Row() { Row() {
Button($r('app.string.Test_failure_success')) Button($r('app.string.Test_failure_success'))
.onClick(() => { .onClick(() => {
this.ImageKnifeOption = new ImageKnifeOption({ this.ImageKnifeOption = {
loadSrc: "https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc: "https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
@ -75,7 +75,7 @@ struct LoadStatePage {
onComplete:(event)=>{ onComplete:(event)=>{
console.error("Load onComplete width:"+event?.width , " height:"+event?.height , " componentWidth:"+event?.componentWidth," componentHeight:" + event?.componentHeight); console.error("Load onComplete width:"+event?.width , " height:"+event?.height , " componentWidth:"+event?.componentWidth," componentHeight:" + event?.componentHeight);
} }
}) }
}) })
} }
.margin({ top: 20 }) .margin({ top: 20 })
@ -85,7 +85,7 @@ struct LoadStatePage {
ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth) ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth)
.margin({ top: 20 }) .margin({ top: 20 })
Button($r('app.string.Custom_download_failed')).onClick(()=>{ Button($r('app.string.Custom_download_failed')).onClick(()=>{
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc: "abc", loadSrc: "abc",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
@ -95,7 +95,7 @@ struct LoadStatePage {
this.message = "err:" + err this.message = "err:" + err
} }
} }
}) }
}).margin({ top: 20 }) }).margin({ top: 20 })
Text(this.message).fontSize(20).margin({ top: 20 }) Text(this.message).fontSize(20).margin({ top: 20 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).height(this.currentHeight).width(this.currentWidth) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).height(this.currentHeight).width(this.currentWidth)
@ -109,7 +109,7 @@ struct LoadStatePage {
} }
// 自定义下载方法 // 自定义下载方法
@Concurrent @Concurrent
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> { async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>): Promise<ArrayBuffer | undefined> {
console.info("ImageKnife:: custom download" + src) console.info("ImageKnife:: custom download" + src)
// 举例写死从本地文件读取,也可以自己请求网络图片 // 举例写死从本地文件读取,也可以自己请求网络图片
return undefined return undefined

View File

@ -12,10 +12,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct LongImagePage { struct LongImagePage {
build() { build() {
@ -25,13 +25,13 @@ struct LongImagePage {
// Image($r("app.media.aaa")).objectFit(ImageFit.Auto).width(200) // Image($r("app.media.aaa")).objectFit(ImageFit.Auto).width(200)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc:"https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg", loadSrc:"https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg",
//src:$r("app.media.aaa"), //src:$r("app.media.aaa"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}) })
} }
.height('100%') .width('100%') .height('100%') .width('100%')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*
* 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 { ImageKnifeComponent,ImageKnife } from '@ohos/libraryimageknife';
import { CommonDataSource } from './model/CommonDataSource';
@Entry
@Component
struct MaxRequest1 {
@State hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([])
private data: Array<string> = []
aboutToAppear(): void {
ImageKnife.getInstance().setMaxRequests(8)
for (let index = 0; index < 200; index++) {
this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`)
}
this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data)
}
build() {
Column() {
WaterFlow() {
LazyForEach(this.hotCommendList,(item: string)=>{
FlowItem() {
Column(){
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: item,
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"),
}
}).width("50%").height(160)
}
}.height(200)
.backgroundColor("#95efd2")
},(item: string) => item)
}.columnsTemplate("1fr 1fr")
.cachedCount(8)
.columnsGap(10)
.rowsGap(5)
.backgroundColor(0xFAEEE0)
.width("100%").height("100%")
}
}
}

View File

@ -0,0 +1,55 @@
/*
* 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 { ImageKnifeComponent,ImageKnife } from '@ohos/libraryimageknife';
import { CommonDataSource } from './model/CommonDataSource';
@Entry
@Component
struct MaxRequest2 {
@State hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([])
private data: Array<string> = []
aboutToAppear(): void {
ImageKnife.getInstance().setMaxRequests(20)
for (let index = 200; index < 400; index++) {
this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`)
}
this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data)
}
build() {
Column() {
WaterFlow() {
LazyForEach(this.hotCommendList,(item: string)=>{
FlowItem() {
Column(){
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: item,
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"),
}
}).width("50%").height(160)
}
}.height(200)
.backgroundColor("#95efd2")
},(item: string) => item)
}.columnsTemplate("1fr 1fr")
.cachedCount(20)
.columnsGap(10)
.rowsGap(5)
.backgroundColor(0xFAEEE0)
.width("100%").height("100%")
}
}
}

View File

@ -0,0 +1,55 @@
/*
* 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 { ImageKnifeComponent,ImageKnife } from '@ohos/libraryimageknife';
import { CommonDataSource } from './model/CommonDataSource';
@Entry
@Component
struct MaxRequest3 {
@State hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([])
private data: Array<string> = []
aboutToAppear(): void {
ImageKnife.getInstance().setMaxRequests(32)
for (let index = 400; index < 600; index++) {
this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`)
}
this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data)
}
build() {
Column() {
WaterFlow() {
LazyForEach(this.hotCommendList,(item: string)=>{
FlowItem() {
Column(){
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: item,
placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"),
}
}).width("50%").height(160)
}
}.height(200)
.backgroundColor("#95efd2")
},(item: string) => item)
}.columnsTemplate("1fr 1fr")
.cachedCount(40)
.columnsGap(10)
.rowsGap(5)
.backgroundColor(0xFAEEE0)
.width("100%").height("100%")
}
}
}

View File

@ -15,49 +15,49 @@
import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct ObjectFitPage { struct ObjectFitPage {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill objectFit: ImageFit.Fill
}) }
build() { build() {
Column() { Column() {
Button($r('app.string.Main_image_Fill')).onClick(()=>{ Button($r('app.string.Main_image_Fill')).onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill objectFit: ImageFit.Fill
}) }
}) })
Button($r('app.string.Maintain_proportion_filling')).margin({top:10}).onClick(async () => { Button($r('app.string.Maintain_proportion_filling')).margin({top:10}).onClick(async () => {
ImageKnife.getInstance().removeAllMemoryCache() ImageKnife.getInstance().removeAllMemoryCache()
await ImageKnife.getInstance().removeAllFileCache() await ImageKnife.getInstance().removeAllFileCache()
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg", loadSrc: "https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg",
placeholderSrc: $r("app.media.app_icon"), placeholderSrc: $r("app.media.app_icon"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill, objectFit: ImageFit.Fill,
placeholderObjectFit: ImageFit.Contain placeholderObjectFit: ImageFit.Contain
}) }
}) })
Button($r('app.string.Error_graph_None')).margin({top:10}).onClick(() => { Button($r('app.string.Error_graph_None')).margin({top:10}).onClick(() => {
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "http://xxxxx", loadSrc: "http://xxxxx",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill, objectFit: ImageFit.Fill,
errorholderObjectFit: ImageFit.None errorholderObjectFit: ImageFit.None
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({

View File

@ -0,0 +1,39 @@
/*
* 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 { router } from '@kit.ArkUI'
@Entry
@Component
struct PrefetchAndCacheCount {
build() {
Column() {
Button("cacheCount == 5")
.onClick(()=>{
router.pushUrl({url:"pages/LazyForEachCache"})
})
Button("cacheCount == 30")
.margin({top:10})
.onClick(()=>{
router.pushUrl({url:"pages/LazyForEachCount"})
})
Button("prefetch + preload")
.margin({top:10})
.onClick(()=>{
router.pushUrl({url:"pages/PrefetchAndPreload"})
})
}.width("100%")
.height("100%")
}
}

View File

@ -0,0 +1,56 @@
/*
* 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 { BasicPrefetcher } from '@kit.ArkUI';
import DataSourcePrefetchingImageKnife, { InfoItem } from './model/DataSourcePrefetching';
import { PageViewModel } from './model/PageViewModel';
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry
@Component
export struct PrefetchAndPreload {
// 创建DataSourcePrefetchingImageKnife对象具备任务预取、取消能力的数据源
private readonly dataSource = new DataSourcePrefetchingImageKnife(PageViewModel.getItems());
// 创建BasicPrefetcher对象默认的动态预取算法实现
private readonly prefetcher = new BasicPrefetcher(this.dataSource);
build() {
Column() {
List({ space: 16 }) {
LazyForEach(this.dataSource, (item: InfoItem,index:number) => {
ListItem() {
Column({ space: 12 }) {
ImageKnifeComponent({
imageKnifeOption:{
loadSrc: item.albumUrl,
placeholderSrc:$r('app.media.loading')
}
}).width(100).height(100)
Text(`${index}`)
}.border({ width: 5 , color: "#000000"})
}
.reuseId('imageKnife')
})
}
.cachedCount(5)
.onScrollIndex((start: number, end: number) => {
// 列表滚动触发visibleAreaChanged实时更新预取范围触发调用prefetch、cancel接口
this.prefetcher.visibleAreaChanged(start, end)
})
.width("100%")
.height("100%")
.margin({ left: 10, right: 10 })
.layoutWeight(1)
}
}
}

View File

@ -0,0 +1,23 @@
import { router } from '@kit.ArkUI'
@Entry
@Component
struct SetMaxRequestPage {
build() {
Column() {
Button("maxRequest = 8")
.onClick(()=>{
router.pushUrl({url:"pages/MaxRequest1"})
})
Button("maxRequest = 20")
.onClick(()=>{
router.pushUrl({url:"pages/MaxRequest2"})
}).margin({top:20})
Button("maxRequest = 32")
.onClick(()=>{
router.pushUrl({url:"pages/MaxRequest2"})
}).margin({top:20})
}.width("100%")
.height("100%")
}
}

View File

@ -16,18 +16,18 @@ import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct SignatureTestPage { struct SignatureTestPage {
@Local imageKnifeOption1: ImageKnifeOption =new ImageKnifeOption( @State imageKnifeOption1: ImageKnifeOption =
{ {
loadSrc: $r('app.media.icon'), loadSrc: $r('app.media.icon'),
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
}); };
@Local imageKnifeOption2: ImageKnifeOption =new ImageKnifeOption( @State imageKnifeOption2: ImageKnifeOption =
{ {
loadSrc: $r('app.media.icon'), loadSrc: $r('app.media.icon'),
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
}); };
build() { build() {
Scroll() { Scroll() {
@ -37,11 +37,11 @@ struct SignatureTestPage {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button($r('app.string.Load')) Button($r('app.string.Load'))
.onClick(() => { .onClick(() => {
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc: 'https://img-blog.csdn.net/20140514114029140', loadSrc: 'https://img-blog.csdn.net/20140514114029140',
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
signature: "1" signature: "1"
}) }
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink) }.width('100%').backgroundColor(Color.Pink)
@ -50,11 +50,11 @@ struct SignatureTestPage {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button($r('app.string.Load')) Button($r('app.string.Load'))
.onClick(() => { .onClick(() => {
this.imageKnifeOption2 = new ImageKnifeOption({ this.imageKnifeOption2 = {
loadSrc: 'https://img-blog.csdn.net/20140514114029140', loadSrc: 'https://img-blog.csdn.net/20140514114029140',
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
signature: new Date().getTime().toString() signature: new Date().getTime().toString()
}) }
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink) }.width('100%').backgroundColor(Color.Pink)

View File

@ -12,19 +12,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,BlurTransformation,ImageKnifeOption } from '@ohos/libraryimageknife'; import { ImageKnifeComponent,BlurTransformation } from '@ohos/libraryimageknife';
import fs from '@ohos.file.fs'; import fs from '@ohos.file.fs';
import image from '@ohos.multimedia.image'; import image from '@ohos.multimedia.image';
import { common2D, drawing } from '@kit.ArkGraphics2D'; import { common2D, drawing } from '@kit.ArkGraphics2D';
@Entry @Entry
@ComponentV2 @Component
struct SingleImage { struct SingleImage {
resource: string = "app.media.svgSample" resource: string = "app.media.svgSample"
scroller: Scroller = new Scroller; scroller: Scroller = new Scroller;
localFile: string = getContext(this).filesDir + "/icon.png" localFile: string = getContext(this).filesDir + "/icon.png"
@Local pixelMap:PixelMap | undefined = undefined; @State pixelMap:PixelMap | undefined = undefined;
@Local DrawingColorFilter: ColorFilter | undefined = undefined @State DrawingColorFilter: ColorFilter | undefined = undefined
private color: common2D.Color = { alpha: 255, red: 255, green: 0, blue: 0 }; private color: common2D.Color = { alpha: 255, red: 255, green: 0, blue: 0 };
aboutToAppear(): void { aboutToAppear(): void {
// 拷贝本地文件 // 拷贝本地文件
@ -46,12 +46,12 @@ struct SingleImage {
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r("app.media.svgSample"), loadSrc: $r("app.media.svgSample"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain objectFit: ImageFit.Contain
}) }
}).width(100).height(100) }).width(100).height(100)
.onClick(()=>{ .onClick(()=>{
this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN); this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN);
@ -60,48 +60,52 @@ struct SingleImage {
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.localFile, loadSrc: this.localFile,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain objectFit: ImageFit.Contain
}) }
}).width(100).height(100) }).width(100).height(100)
Text($r('app.string.Network_images')) Text($r('app.string.Network_images'))
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)} progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)}
}) }
}).width(100).height(100) }).width(100).height(100)
Text($r('app.string.Custom_network_download')) Text($r('app.string.Custom_network_download'))
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg", loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
headerOption:[{
key:"refer",
value:"xx.xx.xx.xx"
}],
customGetImage: custom, customGetImage: custom,
transformation: new BlurTransformation(10) transformation: new BlurTransformation(10)
}) }
}).width(100).height(100) }).width(100).height(100)
Text($r('app.string.PixelMap_loads_images')) Text($r('app.string.PixelMap_loads_images'))
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.pixelMap!, loadSrc: this.pixelMap!,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
}) }
}).width(100).height(100) }).width(100).height(100)
} }
.width('100%') .width('100%')
@ -124,9 +128,11 @@ struct SingleImage {
// 自定义下载方法 // 自定义下载方法
@Concurrent @Concurrent
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> { async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>): Promise<ArrayBuffer | undefined> {
console.info("ImageKnife:: custom download" + src) let refer = headers!["refer"] as string
console.info("ImageKnife:: custom download" + src,"refer:"+refer)
// 举例写死从本地文件读取,也可以自己请求网络图片 // 举例写死从本地文件读取,也可以自己请求网络图片
return context.resourceManager.getMediaContentSync($r("app.media.startIcon").id).buffer as ArrayBuffer let buffer = context.resourceManager.getMediaContentSync($r("app.media.startIcon").id).buffer as ArrayBuffer
return buffer
} }

View File

@ -13,20 +13,20 @@
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnife, CacheStrategy, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'; import { ImageKnife, CacheStrategy, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct TestCacheDataPage { struct TestCacheDataPage {
@Local cacheUpLimit: number = 0; @State cacheUpLimit: number = 0;
@Local currentNum: number = 0; @State currentNum: number = 0;
@Local currentSize: number = 0; @State currentSize: number = 0;
@Local currentWidth: number = 200 @State currentWidth: number = 200
@Local currentHeight: number = 200 @State currentHeight: number = 200
@Local markersLimitText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) @State markersLimitText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory'))
@Local markersNumText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) @State markersNumText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory'))
@Local markersSizeText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory')) @State markersSizeText: string = getContext(this).resourceManager.getStringSync($r('app.string.memory'))
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State ImageKnifeOption: ImageKnifeOption = {
loadSrc: "", loadSrc: "",
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
onLoadListener: { onLoadListener: {
@ -38,7 +38,7 @@ struct TestCacheDataPage {
}, },
}, },
border: { radius: 50 } border: { radius: 50 }
}) }
aboutToAppear(): void { aboutToAppear(): void {
ImageKnife.getInstance().initFileCache(getContext(this), 256, 256 * 1024 * 1024, "ImageKnifeCache1") ImageKnife.getInstance().initFileCache(getContext(this), 256, 256 * 1024 * 1024, "ImageKnifeCache1")
@ -55,21 +55,21 @@ struct TestCacheDataPage {
Button($r('app.string.load_memory')) Button($r('app.string.load_memory'))
.onClick(() => { .onClick(() => {
this.ImageKnifeOption = new ImageKnifeOption({ this.ImageKnifeOption = {
loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg", loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg",
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
writeCacheStrategy: CacheStrategy.Memory, writeCacheStrategy: CacheStrategy.Memory,
border: { radius: 50 }, border: { radius: 50 },
}) }
}) })
Button($r('app.string.load_disk')) Button($r('app.string.load_disk'))
.onClick(() => { .onClick(() => {
this.ImageKnifeOption = new ImageKnifeOption({ this.ImageKnifeOption = {
loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg", loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg",
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
writeCacheStrategy: CacheStrategy.File, writeCacheStrategy: CacheStrategy.File,
border: { radius: 50 }, border: { radius: 50 },
}) }
}) })
Text($r('app.string.cur_cache_limit', this.markersLimitText, this.cacheUpLimit)) Text($r('app.string.cur_cache_limit', this.markersLimitText, this.cacheUpLimit))
.fontSize(20) .fontSize(20)
@ -80,7 +80,7 @@ struct TestCacheDataPage {
Text($r('app.string.cur_cache_size', this.markersSizeText, this.currentSize)).fontSize(20).margin({ bottom: 20 }); Text($r('app.string.cur_cache_size', this.markersSizeText, this.currentSize)).fontSize(20).margin({ bottom: 20 });
Button($r('app.string.get_cur_memory_limit')).onClick(() => { Button($r('app.string.get_cur_memory_limit')).onClick(() => {
let result = ImageKnife.getInstance().getCacheUpperLimit(CacheStrategy.Memory); let result = ImageKnife.getInstance().getCacheLimitSize(CacheStrategy.Memory);
this.markersLimitText = getContext(this).resourceManager.getStringSync($r('app.string.memory')) this.markersLimitText = getContext(this).resourceManager.getStringSync($r('app.string.memory'))
if (result) { if (result) {
this.cacheUpLimit = result / (1024 * 1024); this.cacheUpLimit = result / (1024 * 1024);
@ -89,7 +89,7 @@ struct TestCacheDataPage {
} }
}).margin({ bottom: 8 }); }).margin({ bottom: 8 });
Button($r('app.string.get_img_number_of_cache')).onClick(() => { Button($r('app.string.get_img_number_of_cache')).onClick(() => {
let result = ImageKnife.getInstance().getCurrentPicturesNum(CacheStrategy.Memory); let result = ImageKnife.getInstance().getCurrentCacheNum(CacheStrategy.Memory);
this.markersNumText = getContext(this).resourceManager.getStringSync($r('app.string.memory')) this.markersNumText = getContext(this).resourceManager.getStringSync($r('app.string.memory'))
if (result) { if (result) {
this.currentNum = result; this.currentNum = result;
@ -108,7 +108,7 @@ struct TestCacheDataPage {
}).margin({ bottom: 8 }); }).margin({ bottom: 8 });
Button($r('app.string.get_cur_disk_limit')).onClick(() => { Button($r('app.string.get_cur_disk_limit')).onClick(() => {
let result = ImageKnife.getInstance().getCacheUpperLimit(CacheStrategy.File); let result = ImageKnife.getInstance().getCacheLimitSize(CacheStrategy.File);
this.markersLimitText = getContext(this).resourceManager.getStringSync($r('app.string.disk')) this.markersLimitText = getContext(this).resourceManager.getStringSync($r('app.string.disk'))
if (result) { if (result) {
this.cacheUpLimit = result / (1024 * 1024); this.cacheUpLimit = result / (1024 * 1024);
@ -117,7 +117,7 @@ struct TestCacheDataPage {
} }
}).margin({ bottom: 8 }); }).margin({ bottom: 8 });
Button($r('app.string.get_img_number_of_disk')).onClick(() => { Button($r('app.string.get_img_number_of_disk')).onClick(() => {
let result = ImageKnife.getInstance().getCurrentPicturesNum(CacheStrategy.File); let result = ImageKnife.getInstance().getCurrentCacheNum(CacheStrategy.File);
this.markersNumText = getContext(this).resourceManager.getStringSync($r('app.string.disk')) this.markersNumText = getContext(this).resourceManager.getStringSync($r('app.string.disk'))
if (result) { if (result) {
this.currentNum = result; this.currentNum = result;

View File

@ -74,17 +74,17 @@ struct TestChangeColorPage {
Text($r('app.string.master_image')).margin({ top: 20 }) Text($r('app.string.master_image')).margin({ top: 20 })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.src loadSrc: this.src
}) }
}).width(110).height(110) }).width(110).height(110)
Text($r('app.string.click_img_to_change_color')).margin({ top: 30 }) Text($r('app.string.click_img_to_change_color')).margin({ top: 30 })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.src, loadSrc: this.src,
drawingColorFilter: this.DrawingColorFilterFirst drawingColorFilter: this.DrawingColorFilterFirst
}) }
}) })
.onClick(() => { .onClick(() => {
this.DrawingColorFilterFirst = this.DrawingColorFilterFirst =
@ -93,18 +93,18 @@ struct TestChangeColorPage {
Text($r('app.string.test_non_svg_color')).margin({ top: 30 }) Text($r('app.string.test_non_svg_color')).margin({ top: 30 })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.ic_test_change_color_png'), loadSrc: $r('app.media.ic_test_change_color_png'),
drawingColorFilter: drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN) drawingColorFilter: drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN)
}) }
}).width(110).height(110) }).width(110).height(110)
Text($r('app.string.test_svg_color')).margin({ top: 30 }) Text($r('app.string.test_svg_color')).margin({ top: 30 })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r("app.media.ic_test_change_color_svg"), loadSrc: $r("app.media.ic_test_change_color_svg"),
drawingColorFilter: drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN) drawingColorFilter: drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN)
}) }
}).width(110).height(110) }).width(110).height(110)
}.width('100%').height('100%') }.width('100%').height('100%')

View File

@ -12,10 +12,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent ,ImageKnifeOption} from '@ohos/libraryimageknife'; import { ImageKnifeComponent } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct TestCommonImage { struct TestCommonImage {
private data: Array<string> = [] private data: Array<string> = []
aboutToAppear(): void { aboutToAppear(): void {
@ -30,13 +30,13 @@ struct TestCommonImage {
FlowItem() { FlowItem() {
Column(){ Column(){
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: item, loadSrc: item,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
signature: "aaa" signature: "aaa"
}) }
}).width("50%").height(200) }).width("50%").height(200)
} }
}.height(200) }.height(200)

View File

@ -12,34 +12,34 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestErrorHolderPage { struct TestErrorHolderPage {
build() { build() {
Column() { Column() {
Text("ImageKnifeComponent1").fontSize(20) Text("ImageKnifeComponent1").fontSize(20)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "abc", loadSrc: "abc",
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
}).width(200).height(200) }).width(200).height(200)
Text("ImageKnifeComponent2").fontSize(20) Text("ImageKnifeComponent2").fontSize(20)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "abc", loadSrc: "abc",
errorholderSrc:$r('app.media.startIcon') errorholderSrc:$r('app.media.startIcon')
}) }
}).width(200).height(200) }).width(200).height(200)
Text("ImageKnifeComponent2").fontSize(20) Text("ImageKnifeComponent2").fontSize(20)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "abc", loadSrc: "abc",
errorholderSrc:$r('app.media.mask_starfish') errorholderSrc:$r('app.media.mask_starfish')
}) }
}).width(200).height(200) }).width(200).height(200)
} }
.height('100%') .width('100%') .height('100%') .width('100%')

View File

@ -15,9 +15,9 @@
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestPrefetchToFileCachePage { struct TestPrefetchToFileCachePage {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
headerOption:[ headerOption:[
@ -26,7 +26,7 @@ struct TestPrefetchToFileCachePage {
value:"单个" value:"单个"
} }
] ]
}) }
build() { build() {
Column() { Column() {

View File

@ -15,7 +15,7 @@
import { IndexComponent } from "@ohos/libraryimageknife" import { IndexComponent } from "@ohos/libraryimageknife"
@Entry @Entry
@ComponentV2 @Component
struct TestHspPreLoadImage { struct TestHspPreLoadImage {
build() { build() {
Column() { Column() {

View File

@ -12,9 +12,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@ObservedV2 @Observed
export class MsgModel { export class MsgModel {
id: string id: string
cId: string cId: string
@ -30,10 +30,10 @@ export class MsgModel {
} }
// @Reusable @Reusable
@ComponentV2 @Component
export struct MsgItem { export struct MsgItem {
@Param count: number = 0 count: number = 0
private data: Array<string> = [ private data: Array<string> = [
"http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg", "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg",
"http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg", "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg",
@ -59,37 +59,37 @@ export struct MsgItem {
build(){ build(){
if (this.count % 2 == 0 && this.count <6){ if (this.count % 2 == 0 && this.count <6){
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.startIcon"), loadSrc:$r("app.media.startIcon"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
}else if (this.count > 6 && this.count - 6 < this.data.length){ }else if (this.count > 6 && this.count - 6 < this.data.length){
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:this.data[this.count - 6], loadSrc:this.data[this.count - 6],
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
}else { }else {
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.pngSample"), loadSrc:$r("app.media.pngSample"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
} }
} }
} }
@Entry @Entry
@ComponentV2 @Component
struct ImageTestPage { struct ImageTestPage {
count : number = 0 count : number = 0
rCount: number = 0 rCount: number = 0
scroller: Scroller = new Scroller() scroller: Scroller = new Scroller()
@Local list: MsgModel[] = [] @State list: MsgModel[] = []
@Local imageSize: number =100 @State imageSize: number =100
handAdd(){ handAdd(){
this.count++ this.count++
const msgItem = new MsgModel('add_id'+this.count, 'addBody'+this.count,'cId'+ this.count) const msgItem = new MsgModel('add_id'+this.count, 'addBody'+this.count,'cId'+ this.count)

View File

@ -0,0 +1,412 @@
/*
* 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 { ImageKnifeComponent, ImageKnifeData, ImageKnifeOption, ImageKnifeRequest } from '@ohos/libraryimageknife';
import { router } from '@kit.ArkUI';
@Entry
@Component
struct TestImageKnifeCallbackPage {
@State imageKnifeOption: ImageKnifeOption = {
loadSrc: "",
objectFit: ImageFit.Contain,
border: { radius: 50 }
};
@State currentWidth: number = 200
@State currentHeight: number = 200
@State url: string | undefined = ""
@State imageType: string | undefined = ""
@State imageWidth: number | undefined = 0
@State imageHeight: number | undefined = 0
@State imageSize: number | undefined = 0
@State componentWidth: number | undefined = 0
@State componentHeight: number | undefined = 0
@State frameNum: number | undefined = 0
@State decodeSize: string | undefined = ""
@State err_msg: string | undefined = ""
@State err_phase: string | undefined = ""
@State err_code: number | undefined = 0
@State http_code: number | undefined = 0
@State reqStartTime: string | undefined = ""
@State reqEndTime: string | undefined = ""
@State reqCancelTime: string | undefined = ""
@State memoryStartTime: string | undefined = ""
@State memoryEndTime: string | undefined = ""
@State diskStartTime: string | undefined = ""
@State diskEndTime: string | undefined = ""
@State netStartTime: string | undefined = ""
@State netEndTime: string | undefined = ""
@State decodeStartTime: string | undefined = ""
@State decodeEndTime: string | undefined = ""
@State renderTime: string | undefined = ""
@State showChild: boolean = true;
build() {
Column() {
Text($r('app.string.img_url', this.url)).fontSize(14)
Text($r('app.string.img_format', this.imageType)).fontSize(14)
Text($r('app.string.img_master_size', this.imageWidth, this.imageHeight, this.imageSize)).fontSize(14)
Text($r('app.string.componentWH', this.componentWidth, this.componentHeight)).fontSize(14)
Text($r('app.string.img_frame', this.frameNum)).fontSize(14)
Text($r('app.string.img_content_size', this.decodeSize)).fontSize(14)
Text($r('app.string.err_msg', this.err_msg)).fontSize(14)
Text($r('app.string.err_phase', this.err_phase)).fontSize(14)
Text($r('app.string.err_code', this.err_code)).fontSize(14)
Text($r('app.string.http_code', this.http_code)).fontSize(14)
Text($r('app.string.req_start_time', this.reqStartTime)).fontSize(14)
Text($r('app.string.req_end_time', this.reqEndTime)).fontSize(14)
Text($r('app.string.req_cancel_time', this.reqCancelTime)).fontSize(14)
Text($r('app.string.memory_start_time', this.memoryStartTime)).fontSize(14)
Text($r('app.string.memory_end_time', this.memoryEndTime)).fontSize(14)
Text($r('app.string.disk_start_time', this.diskStartTime)).fontSize(14)
Text($r('app.string.disk_end_time', this.diskEndTime)).fontSize(14)
Text($r('app.string.net_start_time', this.netStartTime)).fontSize(14)
Text($r('app.string.net_end_time', this.netEndTime)).fontSize(14)
Text($r('app.string.decode_start_time', this.decodeStartTime)).fontSize(14)
Text($r('app.string.decode_end_time', this.decodeEndTime)).fontSize(14)
Text($r('app.string.render_time', this.renderTime)).fontSize(14)
Scroll() {
Column() {
Row() {
Button($r('app.string.Network_images'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg",
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
Button($r('app.string.gif'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
Button($r('app.string.local_pic'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
}
Row() {
Button($r('app.string.net_load_failed'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: "https://img-blog.csdn.net/20140514114039140",
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
Button($r('app.string.local_load_failed'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: 'app.media.xxx',
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
Button($r('app.string.share_load_failed'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: 'datashare://ssas',
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
}
Button($r('app.string.test_cancel_callback_btn'))
.fontSize(13)
.onClick(() => {
this.destroy();
this.imageKnifeOption = {
loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg",
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
this.showChild = false;
this.analyzeStartCallBackData(data);
},
onLoadFailed: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
},
onLoadSuccess: (data, imageData, req) => {
this.analyzeSuccessCallBackData(req?.getImageKnifeData());
},
onLoadCancel: (res, req) => {
this.analyzeFailedBackData(res, req?.getImageKnifeData());
}
},
border: { radius: 50 },
onComplete: (event) => {
if (event && event.loadingStatus == 0) {
this.renderTime = this.formatDate(Date.now());
}
}
}
})
Button($r('app.string.list_pic'))
.fontSize(13)
.onClick(() => {
router.push({
url: 'pages/TestListImageKnifeCallbackPage',
});
})
if (this.showChild) {
ImageKnifeComponent(
{ imageKnifeOption: this.imageKnifeOption })
.height(this.currentHeight)
.width(this.currentWidth)
.margin({ top: 20, bottom: 20 })
}
}
.width('100%')
}
}.alignItems(HorizontalAlign.Start)
}
formatDate(time: number | undefined) {
if (!time) {
return;
}
let date = new Date(time);
const year = date.getFullYear().toString()
let month = (date.getMonth() + 1).toString()
let day = date.getDate().toString()
let hour = date.getHours().toString()
let min = date.getMinutes().toString()
let seconds = date.getSeconds().toString()
let mill = date.getMilliseconds();
return `${year}-${month}-${day} ${hour}:${min}:${seconds}:${mill}`
}
analyzeStartCallBackData(req: ImageKnifeRequest | undefined) {
let data = req?.getImageKnifeData();
if (data) {
if (typeof req?.imageKnifeOption.loadSrc == 'string') {
this.url = req?.imageKnifeOption.loadSrc;
}
this.componentWidth = req?.componentWidth;
this.componentHeight = req?.componentHeight;
this.reqStartTime = this.formatDate(data.timeInfo?.requestStartTime);
this.memoryStartTime = this.formatDate(data.timeInfo?.memoryCheckStartTime);
this.memoryEndTime = this.formatDate(data.timeInfo?.memoryCheckEndTime);
}
}
analyzeSuccessCallBackData(data: ImageKnifeData | undefined) {
if (data) {
this.imageWidth = data.imageWidth;
this.imageHeight = data.imageHeight;
this.imageSize = data.bufSize;
this.frameNum = data.frameCount;
this.decodeSize = JSON.stringify(data.decodeImages);
this.imageType = data.type;
this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime);
this.diskStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
this.diskEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
this.netStartTime = this.formatDate(data.timeInfo?.netRequestStartTime);
this.netEndTime = this.formatDate(data.timeInfo?.netRequestEndTime);
this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
}
}
analyzeFailedBackData(res: string, data: ImageKnifeData | undefined) {
if (data) {
this.err_msg = res;
this.err_phase = data.errorInfo?.phase;
this.err_code = data.errorInfo?.code;
this.http_code = data.errorInfo?.httpCode;
this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime);
this.diskStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
this.diskEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
this.netStartTime = this.formatDate(data.timeInfo?.netRequestStartTime);
this.netEndTime = this.formatDate(data.timeInfo?.netRequestEndTime);
this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
this.reqCancelTime = this.formatDate(data.timeInfo?.requestCancelTime)
}
}
destroy() {
this.currentWidth = 200
this.currentHeight = 200
this.url = ""
this.imageType = ""
this.imageWidth = 0
this.imageHeight = 0
this.imageSize = 0
this.componentWidth = 0
this.componentHeight = 0
this.frameNum = 0
this.decodeSize = ""
this.err_msg = ""
this.err_phase = ""
this.err_code = 0
this.http_code = 0
this.reqStartTime = ""
this.reqEndTime = ""
this.reqCancelTime = ""
this.memoryStartTime = ""
this.memoryEndTime = ""
this.diskStartTime = ""
this.diskEndTime = ""
this.netStartTime = ""
this.netEndTime = ""
this.decodeStartTime = ""
this.decodeEndTime = ""
this.renderTime = ""
this.showChild = true;
}
}

View File

@ -15,15 +15,15 @@
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestIsUrlExist { struct TestIsUrlExist {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon'), loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading'), placeholderSrc: $r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local source: PixelMap | string | Resource = $r("app.media.startIcon") @State source: PixelMap | string | Resource = $r("app.media.startIcon")
@Local source1: PixelMap | string | Resource = $r("app.media.startIcon") @State source1: PixelMap | string | Resource = $r("app.media.startIcon")
build() { build() {
Column() { Column() {

View File

@ -0,0 +1,101 @@
/*
* 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 { ImageKnifeComponent} from '@ohos/libraryimageknife';
class ArrayElement {
src: string = "";
w: number = 0;
h: number = 0;
}
@Entry
@Component
struct TestListImageKnifeCallbackPage {
private wid: number = 200;
private hig: number = 200;
private dataArray: ESObject[] = [
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg",
"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg",
"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg',
'https://img-blog.csdn.net/20140514114029140',
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
$r('app.media.pngSample'),
$r('app.media.rabbit')
]
private data: Array<ArrayElement> = [];
aboutToAppear(): void {
for (let i = 0; i < this.dataArray.length; i++) {
let element: ArrayElement = {
src: this.dataArray[i],
w: this.wid -(i*5),
h: this.hig -(i*5)
}
this.data.push(element);
}
}
build() {
List({ space: 3 }) {
ForEach(this.data, (item: ArrayElement) => {
ListItem() {
ImageKnifeComponent({
imageKnifeOption:
{
loadSrc: item.src,
objectFit: ImageFit.Contain,
onLoadListener: {
onLoadStart: (data) => {
console.log("listCache start:{ url:"+data?.imageKnifeOption.loadSrc +",componentWidth:"+data?.componentWidth+",componentHeight:"+data?.componentHeight+"},"
+ JSON.stringify(data?.getImageKnifeData()))
},
onLoadFailed: (res, req) => {
console.log("listCache onLoadFailed:res:" + res + ";" + JSON.stringify(req?.getImageKnifeData()))
},
onLoadSuccess: (data, imageData,req) => {
console.log("listCache onLoadSuccess:" + JSON.stringify(req?.getImageKnifeData()))
},
onLoadCancel: (res, req) => {
console.log("listCache onLoadCancel:res:" + res + ";" + JSON.stringify(req?.getImageKnifeData()))
}
},
border: { radius: 50 },
}
}).height(item.w).width(item.h)
}.width('100%')
}, (item: ArrayElement,index) => (item.src+index))
}.width('100%').height('100%')
}
}

View File

@ -13,20 +13,21 @@
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'; import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct TestLoadCancelListenerPage { struct TestLoadCancelListenerPage {
@Local currentWidth: number = 200 @State currentWidth: number = 200
@Local currentHeight: number = 200 @State currentHeight: number = 200
@Local showChild: boolean = true; @State showChild: boolean = true;
@Local text: string = ""; @State text: string = "";
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State ImageKnifeOption: ImageKnifeOption = {
loadSrc: "", loadSrc: "",
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: 50 } border: { radius: 50 }
}) };
build() { build() {
Column() { Column() {
@ -34,7 +35,8 @@ struct TestLoadCancelListenerPage {
Button($r('app.string.rm_component_of_net')) Button($r('app.string.rm_component_of_net'))
.margin(20) .margin(20)
.onClick(() => { .onClick(() => {
this.ImageKnifeOption = new ImageKnifeOption({ this.clearCache();
this.ImageKnifeOption = {
loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg", loadSrc: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg",
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
onLoadListener: { onLoadListener: {
@ -47,23 +49,24 @@ struct TestLoadCancelListenerPage {
} }
}, },
border: { radius: 50 } border: { radius: 50 }
}) }
}) })
Button($r('app.string.component_display')) Button($r('app.string.component_display'))
.margin(20).onClick(() => { .margin(20).onClick(() => {
this.text = ""; this.text = "";
this.showChild = true; this.showChild = true;
this.ImageKnifeOption = new ImageKnifeOption({ this.ImageKnifeOption = {
loadSrc: "", loadSrc: "",
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: 50 } border: { radius: 50 }
}) }
}) })
Button($r('app.string.rm_component_of_local')) Button($r('app.string.rm_component_of_local'))
.margin(20) .margin(20)
.onClick(() => { .onClick(() => {
this.ImageKnifeOption = new ImageKnifeOption({ this.clearCache();
this.ImageKnifeOption = {
loadSrc: $r('app.media.loading'), loadSrc: $r('app.media.loading'),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
onLoadListener: { onLoadListener: {
@ -76,7 +79,7 @@ struct TestLoadCancelListenerPage {
} }
}, },
border: { radius: 50 } border: { radius: 50 }
}) }
}) })
if (this.showChild) { if (this.showChild) {
@ -91,4 +94,8 @@ struct TestLoadCancelListenerPage {
.height('100%') .height('100%')
.width('100%') .width('100%')
} }
clearCache(){
ImageKnife.getInstance().removeAllMemoryCache();
}
} }

View File

@ -15,19 +15,19 @@
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestPrefetchToFileCachePage { struct TestPrefetchToFileCachePage {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
async preload(url:string) { async preload(url:string) {
let fileCachePath = await ImageKnife.getInstance().preLoadCache(url) let fileCachePath = await ImageKnife.getInstance().preLoadCache(url)
console.log("preload-fileCachePath=="+ fileCachePath) console.log("preload-fileCachePath=="+ fileCachePath)
} }
async preload1(url:string) { async preload1(url:string) {
let fileCachePath = await ImageKnife.getInstance().preLoadCache(new ImageKnifeOption({ loadSrc: url })) let fileCachePath = await ImageKnife.getInstance().preLoadCache({ loadSrc: url })
console.log("preload-fileCachePath1=="+ fileCachePath) console.log("preload-fileCachePath1=="+ fileCachePath)
} }
build() { build() {

View File

@ -15,16 +15,16 @@
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestRemoveCache { struct TestRemoveCache {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon'), loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading'), placeholderSrc: $r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local source: PixelMap | string | Resource = $r("app.media.startIcon"); @State source: PixelMap | string | Resource = $r("app.media.startIcon");
@Local source1: PixelMap | string | Resource = $r("app.media.startIcon"); @State source1: PixelMap | string | Resource = $r("app.media.startIcon");
@Local url: string = ''; @State url: string = '';
build() { build() {
Column() { Column() {

View File

@ -15,42 +15,40 @@
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnife, ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestSetCustomImagePage { struct TestSetCustomImagePage {
@State imageKnifeOption: ImageKnifeOption = {
getResourceString(res:Resource){
return getContext().resourceManager.getStringSync(res.id)
}
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({
loadSrc: $r('app.media.startIcon'), loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
aboutToAppear(): void { aboutToAppear(): void {
ImageKnife.getInstance().setCustomGetImage(custom) ImageKnife.getInstance().setCustomGetImage(custom)
} }
aboutToDisappear(): void { aboutToDisappear(): void {
ImageKnife.getInstance().setCustomGetImage() ImageKnife.getInstance().setCustomGetImage()
} }
getResourceString(res:Resource){
return getContext().resourceManager.getStringSync(res.id)
}
build() { build() {
Column() { Column() {
Button(this.getResourceString($r('app.string.Custom_network_download')) + " a").onClick(()=>{ Button(this.getResourceString($r('app.string.Custom_network_download')) + " a").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption ={
loadSrc: "aaa", loadSrc: "aaa",
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
}) })
Button(this.getResourceString($r('app.string.Custom_network_download')) + " b").onClick(()=>{ Button(this.getResourceString($r('app.string.Custom_network_download')) + " b").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "bbb", loadSrc: "bbb",
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
}) })
Button(this.getResourceString($r('app.string.Custom_network_download')) + " c").onClick(()=>{ Button(this.getResourceString($r('app.string.Custom_network_download')) + " c").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "ccc", loadSrc: "ccc",
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption imageKnifeOption: this.imageKnifeOption
@ -62,8 +60,9 @@ struct TestSetCustomImagePage {
} }
} }
@Concurrent @Concurrent
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> { async function custom(context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>): Promise<ArrayBuffer | undefined> {
console.info("ImageKnife:: custom download" + src) console.info("ImageKnife:: custom download" + src)
// 举例写死从本地文件读取,也可以自己请求网络图片 // 举例写死从本地文件读取,也可以自己请求网络图片
return context.resourceManager.getMediaContentSync($r("app.media.pngSample").id).buffer as ArrayBuffer let buffer = context.resourceManager.getMediaContentSync($r("app.media.pngSample").id).buffer as ArrayBuffer
return buffer
} }

View File

@ -24,12 +24,12 @@ export struct ZuImage {
if (this.src) { if (this.src) {
//当前版本存在bug //当前版本存在bug
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.src, loadSrc: this.src,
placeholderSrc: this.placeholderSrc, placeholderSrc: this.placeholderSrc,
errorholderSrc: this.errorholderSrc ?? this.placeholderSrc, errorholderSrc: this.errorholderSrc ?? this.placeholderSrc,
objectFit: ImageFit.Cover objectFit: ImageFit.Cover
}) }
}) })
} else { } else {
Image(this.placeholderSrc) Image(this.placeholderSrc)

View File

@ -15,55 +15,55 @@
import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestWriteCacheStage { struct TestWriteCacheStage {
@Local imageKnifeOption1: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption1: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local imageKnifeOption2: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption2: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local imageKnifeOption3: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption3: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
build() { build() {
Column() { Column() {
Button($r('app.string.Write_memory_and_file')).margin({top:10}).onClick(async ()=>{ Button($r('app.string.Write_memory_and_file')).margin({top:10}).onClick(async ()=>{
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc:'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', loadSrc:'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
writeCacheStrategy:CacheStrategy.Default writeCacheStrategy:CacheStrategy.Default
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption1 imageKnifeOption: this.imageKnifeOption1
}).width(200).height(200).margin({top:10}) }).width(200).height(200).margin({top:10})
Button($r('app.string.Write_memory')).margin({top:10}).onClick(async ()=>{ Button($r('app.string.Write_memory')).margin({top:10}).onClick(async ()=>{
this.imageKnifeOption2 = new ImageKnifeOption({ this.imageKnifeOption2 = {
loadSrc:"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", loadSrc:"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
writeCacheStrategy:CacheStrategy.Memory writeCacheStrategy:CacheStrategy.Memory
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption2 imageKnifeOption: this.imageKnifeOption2
}).width(200).height(200).margin({top:10}) }).width(200).height(200).margin({top:10})
Button($r('app.string.Write_file')).margin({top:10}).onClick(async ()=>{ Button($r('app.string.Write_file')).margin({top:10}).onClick(async ()=>{
this.imageKnifeOption3 = new ImageKnifeOption({ this.imageKnifeOption3 = {
loadSrc:'https://img-blog.csdn.net/20140514114029140', loadSrc:'https://img-blog.csdn.net/20140514114029140',
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
writeCacheStrategy:CacheStrategy.File writeCacheStrategy:CacheStrategy.File
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption3 imageKnifeOption: this.imageKnifeOption3

View File

@ -17,17 +17,17 @@ import matrix4 from '@ohos.matrix4'
@Entry @Entry
@ComponentV2 @Component
struct TransformPage { struct TransformPage {
private custom_scale:number = 1 private custom_scale:number = 1
@Local matrix1:object = matrix4.identity().scale({ x: 1, y: 1 }) @State matrix1:object = matrix4.identity().scale({ x: 1, y: 1 })
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State ImageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: 50 } border: { radius: 50 }
}) }
build() { build() {
Column() { Column() {

View File

@ -15,50 +15,24 @@
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
// const logger = new imUtils.logger.IMLogger('Avatar') // const logger = new imUtils.logger.IMLogger('Avatar')
@ObservedV2
export class MyStorage { class MyImageOption extends ImageKnifeOption {
static instance:MyStorage | undefined = undefined account?: string
static getInstance(){
if(MyStorage.instance == undefined) {
MyStorage.instance = new MyStorage()
}
return MyStorage.instance
}
@Trace WeLink_Mob_fontSize_multiple: number = 1
} }
@ComponentV2 @Component
export struct UserAvatar { export struct UserAvatar {
@Prop @Watch('userInfoUpdate') userInfo: string = ""
// @Prop userInfo: string = "" // @Prop userInfo: string = ""
imgSize: number = 100 imgSize: number = 100
radius: number = 12 radius: number = 12
borderSize: number = 0 borderSize: number = 0
imgSizes: number = 1 imgSizes: number = 1
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption() @State ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption()
@StorageProp('WeLink_Mob_fontSize_multiple') @Watch('updateImgSize') WeLink_Mob_fontSize_multiple: number = 0
scalable: boolean = true; scalable: boolean = true;
@Local calcImgSize: number = 100 @State calcImgSize: number = 100
@Param userInfo: string = ""
@Monitor('userInfo')
userInfoUpdate() {
// if (uri === 'userInfo' && this.imageKnifeOption.account !== this.userInfo.contactId) return;
// // logger.info(`userInfoUpdate uri=${uri} oldAcc=${this.imageKnifeOption.loadSrc} nowAcc=${this.userInfo.externalHeadUrl}`)
// if (this.userInfo.externalHeadUrl === this.imageKnifeOption.loadSrc && this.userInfo.infoUpdateTime.getTime()
// .toString() === this.imageKnifeOption?.signature?.getKey()) return;
this.ImageKnifeOption = new ImageKnifeOption({
//TODO:写死loadSRC场景变更组件大小所有图片不显示
loadSrc: this.userInfo,
placeholderSrc: $r('app.media.loading'),
errorholderSrc: $r('app.media.failed'),
border: { radius:20,width:5,color:$r('app.color.start_window_background') },
objectFit:ImageFit.Contain
// signature: new ObjectKey(this.userInfo.infoUpdateTime.getTime().toString())
})
}
@Local storage: MyStorage = MyStorage.getInstance()
@Monitor('storage.WeLink_Mob_fontSize_multiple')
updateImgSize() {
this.setImageSize()
}
aboutToAppear(): void { aboutToAppear(): void {
this.userInfoUpdate() this.userInfoUpdate()
this.setImageSize() this.setImageSize()
@ -67,19 +41,39 @@ export struct UserAvatar {
setImageSize() { setImageSize() {
if (!this.scalable) { if (!this.scalable) {
this.calcImgSize = this.imgSize this.calcImgSize = this.imgSize
} else if (this.storage.WeLink_Mob_fontSize_multiple < 0.9) { } else if (this.WeLink_Mob_fontSize_multiple < 0.9) {
this.calcImgSize = this.imgSize * 0.9 this.calcImgSize = this.imgSize * 0.9
} else if (this.storage.WeLink_Mob_fontSize_multiple > 1.6) { } else if (this.WeLink_Mob_fontSize_multiple > 1.6) {
this.calcImgSize = this.imgSize * 1.6 this.calcImgSize = this.imgSize * 1.6
} else { } else {
this.calcImgSize = this.imgSize * this.storage.WeLink_Mob_fontSize_multiple this.calcImgSize = this.imgSize * this.WeLink_Mob_fontSize_multiple
} }
} }
updateImgSize() {
this.setImageSize()
}
aboutToReuse(param: ESObject) { aboutToReuse(param: ESObject) {
this.userInfoUpdate() this.userInfoUpdate()
} }
userInfoUpdate() {
// if (uri === 'userInfo' && this.imageKnifeOption.account !== this.userInfo.contactId) return;
// // logger.info(`userInfoUpdate uri=${uri} oldAcc=${this.imageKnifeOption.loadSrc} nowAcc=${this.userInfo.externalHeadUrl}`)
// if (this.userInfo.externalHeadUrl === this.imageKnifeOption.loadSrc && this.userInfo.infoUpdateTime.getTime()
// .toString() === this.imageKnifeOption?.signature?.getKey()) return;
this.ImageKnifeOption = {
//TODO:写死loadSRC场景变更组件大小所有图片不显示
loadSrc: this.userInfo,
placeholderSrc: $r('app.media.loading'),
errorholderSrc: $r('app.media.failed'),
border: { radius:20,width:5,color:$r('app.color.start_window_background') },
objectFit:ImageFit.Contain
// signature: new ObjectKey(this.userInfo.infoUpdateTime.getTime().toString())
}
}
build() { build() {
Row() { Row() {
// Image(this.imageKnifeOption.loadSrc) // Image(this.imageKnifeOption.loadSrc)

View File

@ -12,52 +12,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { MyStorage, UserAvatar } from './User' import { CommonDataSource } from './model/CommonDataSource'
import { UserAvatar } from './User'
class CommonDataSource <T> implements IDataSource {
private dataArray: T[] = []
private listeners: DataChangeListener[] = []
constructor(element: []) {
this.dataArray = element
}
public getData(index: number) {
return this.dataArray[index]
}
public totalCount(): number {
return this.dataArray.length
}
public addData(index: number, data: T[]): void {
this.dataArray = this.dataArray.concat(data)
this.notifyDataAdd(index)
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
this.listeners.splice(pos, 1);
}
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener)
}
}
notifyDataAdd(index: number): void {
this.listeners.forEach((listener: DataChangeListener) => {
listener.onDataAdd(index)
})
}
}
@Entry @Entry
@ComponentV2 @Component
struct Index { struct Index {
@Local hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([]) @State hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([])
private data:string[] = [ private data:string[] = [
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg", "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg",
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg", "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg",
@ -85,42 +46,26 @@ struct Index {
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
] ]
aboutToAppear(): void { aboutToAppear(): void {
MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 1 this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data)
AppStorage.set("WeLink_Mob_fontSize_multiple",1)
} }
build() { build() {
Column() { Column() {
Button("bigger").onClick(()=>{ Button("bigger").onClick(()=>{
MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 1.6 AppStorage.set("WeLink_Mob_fontSize_multiple",1.6)
}) })
Button("small").onClick(()=>{ Button("small").onClick(()=>{
MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 0.8 AppStorage.set("WeLink_Mob_fontSize_multiple",0.8)
}) })
List(){ List(){
// LazyForEach(this.hotCommendList,(item:string)=>{ LazyForEach(this.hotCommendList,(item:string)=>{
// ListItem(){ ListItem(){
// ReuseImage({ ReuseImage({
// userInfo:item userInfo:item
// }).width("100%").height("100%").backgroundColor(Color.Yellow) }).width("100%").height("100%").backgroundColor(Color.Yellow)
// }.width(200).height(200).margin({bottom:5}) }.width(200).height(200).margin({bottom:5})
// }) })
Repeat(this.data)
.each((repeatItem)=>{
ListItem(){
ReuseImage({
userInfo:repeatItem.item
}).width("100%").height("100%").backgroundColor(Color.Yellow)
}.width(200).height(200).margin({bottom:5}).key("reuse")
})
.key(item => item+"reuse")
.virtualScroll()
.template("1",(repeatItem)=>{
ListItem(){
ReuseImage({
userInfo:repeatItem.item
}).width("100%").height("100%").backgroundColor(Color.Yellow)
}.width(200).height(200).margin({bottom:5}).key("reuse")
})
} }
// .cachedCount(20) // .cachedCount(20)
.width("100%") .width("100%")
@ -131,13 +76,13 @@ struct Index {
} }
// @Reusable @Reusable
@ComponentV2 @Component
struct ReuseImage { struct ReuseImage {
@Param userInfo:string = "" @State userInfo:string = ""
// aboutToReuse(params: ESObject): void { aboutToReuse(params: ESObject): void {
// this.userInfo = params.userInfo this.userInfo = params.userInfo
// } }
build() { build() {
Column(){ Column(){

View File

@ -18,15 +18,15 @@ import { photoAccessHelper } from '@kit.MediaLibraryKit';
@Entry @Entry
@ComponentV2 @Component
struct DataShareUriLoadPage { struct DataShareUriLoadPage {
@Local imageKnifeOption1: ImageKnifeOption = @State imageKnifeOption1: ImageKnifeOption =
new ImageKnifeOption({ {
loadSrc: $r('app.media.icon'), loadSrc: $r('app.media.icon'),
placeholderSrc: $r('app.media.loading'), placeholderSrc: $r('app.media.loading'),
errorholderSrc: $r('app.media.failed') errorholderSrc: $r('app.media.failed')
}); };
build() { build() {
@ -43,10 +43,10 @@ struct DataShareUriLoadPage {
let photoViewPicker = new photoAccessHelper.PhotoViewPicker(); let photoViewPicker = new photoAccessHelper.PhotoViewPicker();
let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions); let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions);
uris = photoSelectResult.photoUris; uris = photoSelectResult.photoUris;
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc: uris[0], loadSrc: uris[0],
placeholderSrc:$r('app.media.loading') placeholderSrc:$r('app.media.loading')
}) }
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink) }.width('100%').backgroundColor(Color.Pink)

View File

@ -0,0 +1,60 @@
/*
* 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 { statfs } from '@kit.CoreFileKit'
import { rcp } from '@kit.RemoteCommunicationKit'
export class CommonDataSource <T> implements IDataSource {
private dataArray: T[] = []
private listeners: DataChangeListener[] = []
constructor(element: []) {
this.dataArray = element
}
public getData(index: number) {
return this.dataArray[index]
}
public totalCount(): number {
return this.dataArray.length
}
public addData(index: number, data: T[]): void {
this.dataArray = this.dataArray.concat(data)
this.notifyDataAdd(index)
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
this.listeners.splice(pos, 1);
}
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener)
}
}
notifyDataAdd(index: number): void {
this.listeners.forEach((listener: DataChangeListener) => {
listener.onDataAdd(index)
})
}
}
export class GetSession {
static session:rcp.Session = rcp.createSession()
}

View File

@ -0,0 +1,93 @@
/*
* 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 {ImageKnife, ImageKnifeRequest} from "@ohos/libraryimageknife"
import { IDataSourcePrefetching } from '@kit.ArkUI';
import { HashMap } from '@kit.ArkTS';
const IMADE_UNAVAILABLE = $r('app.media.failed')
export interface InfoItem {
albumUrl: string | Resource
}
export default class DataSourcePrefetchingImageKnife implements IDataSourcePrefetching {
private dataArray: Array<InfoItem>
private readonly requestList: HashMap<number,ImageKnifeRequest> = new HashMap()
private listeners: DataChangeListener[] = [];
constructor(dataArray: Array<InfoItem>) {
this.dataArray = dataArray;
}
public getData(index: number) {
return this.dataArray[index]
}
public totalCount(): number {
return this.dataArray.length
}
public addData(index: number, data: InfoItem[]): void {
this.dataArray = this.dataArray.concat(data)
this.notifyDataAdd(index)
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
this.listeners.splice(pos, 1);
}
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener)
}
}
notifyDataAdd(index: number): void {
this.listeners.forEach((listener: DataChangeListener) => {
listener.onDataAdd(index)
})
}
async prefetch(index: number): Promise<void> {
let item = this.dataArray[index]
if (typeof item.albumUrl == "string") {
// 图片预加载
let request = ImageKnife.getInstance().preload({
loadSrc:item.albumUrl,
onLoadListener:{
onLoadSuccess:()=>{
// 预加载成功,删除成功请求
this.requestList.remove(index)
},
onLoadFailed:()=>{
// 移除失败请求
this.requestList.remove(index)
}
}
})
this.requestList.set(index,request)
}
}
// 取消请求处理
cancel(index: number) {
if(this.requestList.hasKey(index)) {
// 返回MAP对象指定元素
const request = this.requestList.get(index)
// 取消请求
ImageKnife.getInstance().cancel(request)
// 移除被取消的请求对象
this.requestList.remove(index)
}
}
}

View File

@ -0,0 +1,146 @@
/*
* 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 { InfoItem } from './DataSourcePrefetching'
export class PageViewModel {
private static dataArray: Array<InfoItem> = [
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e2/v3/4zI1Xm_3STmV30aZXWRrKw/6aN7WodDRUiBApgffiLPCg.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/42/v3/2dSQCqERTP2TTPyssOMEbQ/zL1ebnKKQ_ilqTDcwCAkOw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/78/v3/qQJpAtRGQe2e_VhbGHDgIw/b3zlit99S6GybD3XdNwqJw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/55/v3/5DZ2LLqYSsK85-shqgLveQ/7ZXcyCWNTvOzQP5FFLBGkg.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3e/v3/LqRoLI-PRSu9Nqa8KdJ-pQ/dSqskBpSR9eraAMn7NBdqA.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/25/v3/jgB2ekkTRX-3yTYZalnANQ/xff_x9cbSPqb7fbNwgJa7A.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/alXwXLHKSyCAIWt_ydgD2g/BCCuu25TREOitQxM7eYOEw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/16/v3/fm2tO4TsRH6mv_D_nSSd5w/FscLpLwQQ-KuV7oaprFK2Q.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/89/v3/UAUvtPHqRD-GWWANsEC57Q/zcRJCQebQ322Aby4jzmwmQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/tUUzzx73R4yp8G--lMhuWQ/EBbcu_dLTT-Jj68XAh6mtA.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/76/v3/EyF6z4FISpCHhae38eEexw/OtyAiu-zSSevNQYvUdtVmA.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/37/v3/12rH1yiEQmK9wlOOcy5avQ/RzBXiEBRRqOC7LRkwNj6VA.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/9a/v3/TpRN4AIzRoyUXIqWdKoE0g/ShOnD_tfS46HDbpSWhbCkQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/03/v3/H3X17s8eTdS2w56JgbB5jQ/a45sT-j8Sbe8sSQXTzeYvQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/10/v3/qaEzwkU0QeKb1yehnP2Xig/q7fxAlgMQKup-HUBayRLGQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/96/v3/rMJJoAflTDSWa1z2pHs2wg/8dOqD0GlQBOCL5AvQok9FQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/d9/v3/FSZH0aTdSqWxeAaxoPvi0g/RqxPxUCXQFiTMBfKTF9kkw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/bf/v3/lSjrRwFcS-ez6jp1ALSQFg/0n7R7XinSPyrYLqDu_1dfw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/8a/v3/ZKzYV5BJTuCk5hCE0y_xNA/8JT95OQnSZSd6_xQQUONhQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/1/v3/sTXb_I7URBKjdMyLDYa19w/qpcwa_FNQmi3-EzjbGsJ8A.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e5/v3/m7wFvw_eQIuDV0Mk0IKi8g/gJU4migzTHKYk5KrgdZbBw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/3f/v3/k_UWbB5_RGW7JemQZ0OQdw/_DUdmaZRQyG-Oyvkb663Bw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/39/v3/rFRN7G_VSo-p4mBjTZtkRw/gBwTI-ieSIqSsSmLNBEcgw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/04/v3/6K8BPYKVQFOr7KCuAG9nog/qKd3pZlrQy2M-feB3ycVPA.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/7d/v3/f0GQFzm1T6eduVeMUhO3Wg/-4cvzIJiRCegjIno3ofIbQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e4/v3/C0xxsSeySxW-2iYR5OEbpQ/f1GlaD3zTeKPX8Vd-M1oVQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/c2/v3/32LCyXN4TuWKWcdf9gAwWw/ej14_BCJQNCaWOKoI9aZAw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fd/v3/LyYJMdMmQNaC5GyBYEZ5Pw/uFLiovypRSagKyIS-UJPVw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/15/v3/MHM9KaWGTgubn6M8-B_6nw/1YO9JyYhTHSBWsoiqYkGZw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/4c/v3/UdYfbv1_QYqn_ulDHp89OA/VkjexMluTqGO3yt3gPK1DA.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/e8/v3/N8blT_7qSK-tRtahIyov7g/M_kjGEEmSzOlTc47Zrfozg.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/28/v3/VS_h3m4YRrSgbgxnqE3vtQ/h-2Q1Qy2SSGEuXM36-Rq_w.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/2e/v3/R-BaM5ToRNGq5rwtNTcnww/Q2e01VHiR2y9KtFaZmpmNQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/88/v3/3djkAJKKTdC539XqMdstSg/wHO7DxvXQS2xbt2Y_-4BNg.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/fb/v3/guw4eiggR3uWjscFTxITYg/TzRB35iPTdCztrZUUaNuFg.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/93/v3/UvSh_f1LT66i0-3hvsYN_A/eYnE3Z8YT5Sk7F-vS2ZmCQ.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/5/v3/tv8Vqf9hQrKpozGeZWg2mw/VEICB-bmQYi0Iv6TGADbhw.jpg"
},
{
albumUrl: "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/30/v3/4v1Ot5BRR6OFVQ9MGn9Xxg/xrPgRn0LS1ep-r7ewIuwiw.jpg"
},
]
static getItems() {
return PageViewModel.dataArray
}
}

View File

@ -5,8 +5,9 @@
"description": "$string:module_desc", "description": "$string:module_desc",
"mainElement": "EntryAbility", "mainElement": "EntryAbility",
"deviceTypes": [ "deviceTypes": [
"default", "phone",
"tablet" "tablet",
"2in1"
], ],
"deliveryWithInstall": true, "deliveryWithInstall": true,
"installationFree": false, "installationFree": false,
@ -42,6 +43,15 @@
], ],
"when": "always" "when": "always"
} }
},
{
"name": "ohos.permission.GET_NETWORK_INFO",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
} }
] ]
} }

View File

@ -369,20 +369,12 @@
"value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally" "value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally"
}, },
{ {
"name": "Image_Downsampling_Functionality", "name": "Network_reload",
"value": "Downscale Image effect" "value": "Network recovery reload"
}, },
{ {
"name": "Sampling_pecification", "name": "preloading_prefetch",
"value": "降采样规格" "value": "Dynamic preloading prefetch"
},
{
"name": "Unreal_samples",
"value": "未降采样大小"
},
{
"name": "After_the_sampling",
"value": "降采样后大小"
}, },
{ {
"name": "image_format", "name": "image_format",
@ -511,6 +503,134 @@
{ {
"name": "disk", "name": "disk",
"value": "Disk" "value": "Disk"
},
{
"name": "Customize_RCP_network",
"value": "Customize RCP network request"
},
{
"name": "request_concurrency",
"value": "Set request concurrency"
},
{
"name": "test_callback",
"value": "test callback data of load pic"
},
{
"name": "gif",
"value": "gif"
},
{
"name": "local_pic",
"value": "local picture"
},
{
"name": "share_pic",
"value": "share picture"
},
{
"name": "net_load_failed",
"value": "netWork load failed"
},
{
"name": "local_load_failed",
"value": "local load failed"
},
{
"name": "share_load_failed",
"value": "shared load failed"
},
{
"name": "list_pic",
"value": "load picture list"
},
{
"name": "img_url",
"value": "url of the service setting:%s"
},
{
"name": "img_format",
"value": "picture format:%s"
},
{
"name": "img_master_size",
"value": "the original width and height of the picture-w%d ,h%d, size%d"
},
{
"name": "componentWH",
"value": "component width and height-w%d ,h%d "
},
{
"name": "img_frame",
"value": "the number of frames of the picture:%d "
},
{
"name": "img_content_size",
"value": "picture decoded width and height size:%s "
},
{
"name": "err_msg",
"value": "error message:%s "
},
{
"name": "err_phase",
"value": "error phase:%s "
},
{
"name": "err_code",
"value": "error code:%d "
},
{
"name": "http_code",
"value": "http code:%d "
},
{
"name": "req_start_time",
"value": "image request start time point:%s "
},
{
"name": "req_end_time",
"value": "the point in time at which the image request ends:%s "
},
{
"name": "req_cancel_time",
"value": "the point at which the image request is cancelled:%s "
},
{
"name": "memory_start_time",
"value": "start checking the memory cache point in time:%s "
},
{
"name": "memory_end_time",
"value": "end Check the memory cache time point:%s "
},
{
"name": "disk_start_time",
"value": "start checking the disk cache point in time:%s "
},
{
"name": "disk_end_time",
"value": "end Check the disk cache time point:%s "
},
{
"name": "net_start_time",
"value": "start time of the network request:%s "
},
{
"name": "net_end_time",
"value": "end time of the network request:%s:%s "
},
{
"name": "decode_start_time",
"value": "decoding start time point:%s "
},
{
"name": "decode_end_time",
"value": "decoding end time point:%s "
},
{
"name": "render_time",
"value": "render successful time:%s "
} }
] ]
} }

View File

@ -3,6 +3,7 @@
"pages/Index", "pages/Index",
"pages/ListPage", "pages/ListPage",
"pages/SingleImage", "pages/SingleImage",
"pages/ManyPhotoShowPage",
"pages/LongImagePage", "pages/LongImagePage",
"pages/TransformPage", "pages/TransformPage",
"pages/UserPage", "pages/UserPage",
@ -23,9 +24,20 @@
"pages/TestSetCustomImagePage", "pages/TestSetCustomImagePage",
"pages/TestErrorHolderPage", "pages/TestErrorHolderPage",
"pages/TestTaskResourcePage", "pages/TestTaskResourcePage",
"pages/DownSamplePage", "pages/ImageKnifeReload",
"pages/LazyForEachCount",
"pages/LazyForEachCache",
"pages/PrefetchAndCacheCount",
"pages/PrefetchAndPreload",
"pages/TestCacheDataPage", "pages/TestCacheDataPage",
"pages/TestChangeColorPage", "pages/TestChangeColorPage",
"pages/TestLoadCancelListenerPage" "pages/TestLoadCancelListenerPage",
"pages/CustomNetImagePage",
"pages/SetMaxRequestPage",
"pages/MaxRequest1",
"pages/MaxRequest2",
"pages/MaxRequest3",
"pages/TestImageKnifeCallbackPage",
"pages/TestListImageKnifeCallbackPage"
] ]
} }

View File

@ -19,6 +19,362 @@
{ {
"name": "app_permission_READ_IMAGEVIDEO", "name": "app_permission_READ_IMAGEVIDEO",
"value": "获取读媒体资源权限" "value": "获取读媒体资源权限"
},
{
"name": "Test_ImageAnimator",
"value": "Test ImageAnimator component"
},
{
"name": "Test_multiple_images",
"value": "Test loading multiple identical images"
},
{
"name": "Test_Task_error",
"value": "Test placeholder map Task error"
},
{
"name": "Test_HSP",
"value": "Test HSP scene preloading"
},
{
"name": "Test_SingleImage",
"value": "SingleImage"
},
{
"name": "Test_custom_download",
"value": "Global custom download"
},
{
"name": "Multiple_images",
"value": "Multiple images"
},
{
"name": "Display_long_image",
"value": "Display long image"
},
{
"name": "Image_scaling",
"value": "Image scaling"
},
{
"name": "Message_list",
"value": "Message list"
},
{
"name": "Custom_cache_key",
"value": "Custom cache key"
},
{
"name": "Preloading_images_to_cache",
"value": "Preloading images to file cache"
},
{
"name": "Retrieve_image_display_from_cache",
"value": "Retrieve image display from cache"
},
{
"name": "Test_single_request_header",
"value": "Test a single request header"
},
{
"name": "Test_write_cache_strategy",
"value": "Test write cache strategy"
},
{
"name": "Image_Transformation",
"value": "Image Transformation"
},
{
"name": "Different_ObjectFit",
"value": "Different ObjectFit"
},
{
"name": "Test_image_loading_success_or_failure_events",
"value": "Test image loading success/failure events"
},
{
"name": "Test_removing_image_cache_interface",
"value": "Test removing image cache interface"
},
{
"name": "Test_error_image_display",
"value": "Test error image display"
},
{
"name": "Test_media_URL",
"value": "Test media URL"
},
{
"name": "Display_the_first_frame",
"value": "Display the first frame of the animation"
},
{
"name": "Display_the_last_frame",
"value": "Display the last frame of the animation"
},
{
"name": "Play",
"value": "Play"
},
{
"name": "Pause",
"value": "Pause"
},
{
"name": "Stop",
"value": "Stop"
},
{
"name": "Infinite_loop",
"value": "Infinite loop"
},
{
"name": "Play_once",
"value": "Play once"
},
{
"name": "Play_twice",
"value": "Play twice"
},
{
"name": "Local_SVG",
"value": "Local SVG image"
},
{
"name": "Under_context_file",
"value": "Files under context file"
},
{
"name": "Network_images",
"value": "Network images"
},
{
"name": "Custom_network_download",
"value": "Custom network download"
},
{
"name": "PixelMap_loads_images",
"value": "PixelMap loads images"
},
{
"name": "Enlarge",
"value": "Enlarge"
},
{
"name": "Reduce",
"value": "Reduce"
},
{
"name": "Click_on_add",
"value": "Click on the size to add 50"
},
{
"name": "Click_on_reduce",
"value": "Click to reduce size by 50"
},
{
"name": "The_key_fixed_1",
"value": "The key is fixed at 1"
},
{
"name": "The_key_changes_timestamp",
"value": "Key changes every time: timestamp"
},
{
"name": "Load",
"value": "Load"
},
{
"name": "Preloading_images_to_file_cache_using_URL",
"value": "Preloading images to file cache using URL"
},
{
"name": "Preloading_images_to_file_cache_using_option",
"value": "Preloading images to file cache using option"
},
{
"name": "Load_image_offline_after_preloading",
"value": "Load image (can be loaded offline after preloading)"
},
{
"name": "Preloading_GIF",
"value": "Preloading GIF"
},
{
"name": "Retrieve_GIF_from_memory",
"value": "Retrieve GIF from memory cache"
},
{
"name": "Retrieve_GIF_from_disk",
"value": "Retrieve GIF from disk cache"
},
{
"name": "Preloading_static_images",
"value": "Preloading static images"
},
{
"name": "Retrieve_images_from_memory",
"value": "Retrieve images from memory cache"
},
{
"name": "Retrieve_images_from_disk",
"value": "Retrieve images from memory disk"
},
{
"name": "Write_memory_and_file",
"value": "Write to memory and file cache"
},
{
"name": "Write_memory",
"value": "Write to memory cache"
},
{
"name": "Write_file",
"value": "Write to file cache"
},
{
"name": "Main_image_Fill",
"value": "Main image Fill Stretch Fill"
},
{
"name": "Maintain_proportion_filling",
"value": "Maintain proportion filling in the placeholder map 'Include'"
},
{
"name": "Error_graph_None",
"value": "Error graph None remains unchanged"
},
{
"name": "Test_failure_success",
"value": "Test failure/success"
},
{
"name": "Custom_download_failed",
"value": "Custom download failed"
},
{
"name": "Retrieve_media_gallery",
"value": "Retrieve the URI of the media gallery and display it using ImageKnife"
},
{
"name": "Click_load_Uri",
"value": "Click to load Uri and display"
},
{
"name": "Delete_all_caches",
"value": "Delete all caches"
},
{
"name": "Delete_all_memory_caches",
"value": "Delete all memory caches"
},
{
"name": "Delete_all_file_caches",
"value": "Delete all file caches"
},
{
"name": "Delete_all_custom_memory_caches",
"value": "Delete all custom memory caches"
},
{
"name": "Delete_all_custom_file_caches",
"value": "Delete all custom file caches"
},
{
"name": "Blur_effect",
"value": "Blur effect"
},
{
"name": "Highlighting_effect",
"value": "Highlighting effect"
},
{
"name": "Ashing_effect",
"value": "Ashing effect"
},
{
"name": "Inverse_effect",
"value": "Inverse effect"
},
{
"name": "Animation_filter_effect",
"value": "Animation filter effect"
},
{
"name": "Crop_circular_effect",
"value": "Crop circular effect"
},
{
"name": "Crop_circular_with_border_effect",
"value": "Crop circular with border effect"
},
{
"name": "Contrast_effect",
"value": "Contrast effect"
},
{
"name": "Black_ink_filtering_effect",
"value": "Black ink filtering effect"
},
{
"name": "Rotate",
"value": "Rotate"
},
{
"name": "Corners",
"value": "Corners"
},
{
"name": "Kuwahara_Filter_effect",
"value": "Kuwahara filter effect"
},
{
"name": "Pixelated_Filter_effect",
"value": "Pixelated filtering effect"
},
{
"name": "Sketch_Filter_effect",
"value": "Sketch Filter effect"
},
{
"name": "Distortion_Filter_effect",
"value": "Distortion Filter effect"
},
{
"name": "Decorative_Filter_effect",
"value": "Decorative Filter effect"
},
{
"name": "Square_cutting_effect",
"value": "Square cutting effect"
},
{
"name": "Top_cutting_effect",
"value": "Top cutting effect"
},
{
"name": "Middle_cutting_effect",
"value": "Middle cutting effect"
},
{
"name": "Bottom_cutting_effect",
"value": "Bottom cutting effect"
},
{
"name": "Mask_effect",
"value": "Mask effect"
},
{
"name": "TIPS",
"value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally"
},
{
"name": "Network_reload",
"value": "Network recovery reload"
},
{
"name": "preloading_prefetch",
"value": "Dynamic preloading prefetch"
} }
] ]
} }

View File

@ -365,20 +365,12 @@
"value": "测试失败场景请先关闭网络,并保证本地没有此网络图片的缓存" "value": "测试失败场景请先关闭网络,并保证本地没有此网络图片的缓存"
}, },
{ {
"name": "Image_Downsampling_Functionality", "name": "Network_reload",
"value": "降采样功能" "value": "网络恢复reload"
}, },
{ {
"name": "Sampling_pecification", "name": "preloading_prefetch",
"value": "降采样规格" "value": "动态预加载prefetch"
},
{
"name": "Unreal_samples",
"value": "未降采样大小"
},
{
"name": "After_the_sampling",
"value": "降采样后大小"
}, },
{ {
"name": "image_format", "name": "image_format",
@ -507,6 +499,134 @@
{ {
"name": "disk", "name": "disk",
"value": "磁盘" "value": "磁盘"
},
{
"name": "Customize_RCP_network",
"value": "自定义rcp网络请求"
},
{
"name": "request_concurrency",
"value": "设置请求并发度"
},
{
"name": "test_callback",
"value": "测试图片加载回调数据"
},
{
"name": "gif",
"value": "gif"
},
{
"name": "local_pic",
"value": "本地图片"
},
{
"name": "share_pic",
"value": "共享图片"
},
{
"name": "net_load_failed",
"value": "网络加载失败"
},
{
"name": "local_load_failed",
"value": "本地加载失败"
},
{
"name": "share_load_failed",
"value": "共享图片加载失败"
},
{
"name": "list_pic",
"value": "加载图片列表"
},
{
"name": "img_url",
"value": "业务设置的url:%s"
},
{
"name": "img_format",
"value": "图片的格式:%s"
},
{
"name": "img_master_size",
"value": "图片的原始宽高大小-宽:%d ,高:%d, 大小:%d"
},
{
"name": "componentWH",
"value": "component的宽高-宽:%d ,高:%d "
},
{
"name": "img_frame",
"value": "图片的帧数:%d "
},
{
"name": "img_content_size",
"value": "图片解码后宽高大小:%s "
},
{
"name": "err_msg",
"value": "错误信息:%s "
},
{
"name": "err_phase",
"value": "发生错误阶段:%s "
},
{
"name": "err_code",
"value": "错误code:%d "
},
{
"name": "http_code",
"value": "网络请求code:%d "
},
{
"name": "req_start_time",
"value": "图片的请求开始时间点:%s "
},
{
"name": "req_end_time",
"value": "图片请求结束的时间点:%s "
},
{
"name": "req_cancel_time",
"value": "图片请求取消的时间点:%s "
},
{
"name": "memory_start_time",
"value": "开始检查内存缓存时间点:%s "
},
{
"name": "memory_end_time",
"value": "结束检查内存缓存时间点:%s "
},
{
"name": "disk_start_time",
"value": "开始检查磁盘缓存时间点:%s "
},
{
"name": "disk_end_time",
"value": "结束检查磁盘缓存时间点:%s "
},
{
"name": "net_start_time",
"value": "网络请求开始时间点:%s "
},
{
"name": "net_end_time",
"value": "网络请求结束时间点:%s "
},
{
"name": "decode_start_time",
"value": "解码开始时间点:%s "
},
{
"name": "decode_end_time",
"value": "解码结束时间点:%s "
},
{
"name": "render_time",
"value": "渲染成功的时间:%s "
} }
] ]
} }

View File

@ -55,12 +55,12 @@ export default function DefaultJobQueueTest() {
expect(job.getQueueLength()).assertEqual(7) expect(job.getQueueLength()).assertEqual(7)
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("high1") expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("high1")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium4")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium3")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium2")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium1") expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium1")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low2") expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium2")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium3")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("medium4")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low1") expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low1")
expect(job.pop()!.imageKnifeOption.loadSrc).assertEqual("low2")
expect(job.pop()).assertEqual(undefined) expect(job.pop()).assertEqual(undefined)
expect(job.getQueueLength()).assertEqual(0) expect(job.getQueueLength()).assertEqual(0)
@ -70,10 +70,10 @@ export default function DefaultJobQueueTest() {
} }
function makeRequest(src: string, context: common.UIAbilityContext, priority?: taskpool.Priority): ImageKnifeRequest { function makeRequest(src: string, context: common.UIAbilityContext, priority?: taskpool.Priority): ImageKnifeRequest {
let option: ImageKnifeOption = new ImageKnifeOption({ let option: ImageKnifeOption = {
loadSrc: src, loadSrc: src,
priority: priority priority: priority
}) }
return new ImageKnifeRequest( return new ImageKnifeRequest(
option, option,
context, context,

View File

@ -153,9 +153,9 @@ export default function FileLruCacheTest() {
}); });
it('fileCacheEngineKey', 0, () => { it('fileCacheEngineKey', 0, () => {
let engineKey: IEngineKey = new DefaultEngineKey() let engineKey: IEngineKey = new DefaultEngineKey()
let imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ let imageKnifeOption: ImageKnifeOption = {
loadSrc:"abc" loadSrc:"abc"
}) }
let imageKey = engineKey.generateFileKey(imageKnifeOption.loadSrc,"") let imageKey = engineKey.generateFileKey(imageKnifeOption.loadSrc,"")
let imageAnimatorKey = engineKey.generateFileKey(imageKnifeOption.loadSrc,"",true) let imageAnimatorKey = engineKey.generateFileKey(imageKnifeOption.loadSrc,"",true)
expect(imageKey == imageAnimatorKey).assertFalse() expect(imageKey == imageAnimatorKey).assertFalse()

View File

@ -40,10 +40,10 @@ export default function ImageKnifeTest() {
it('removeMemoryCache', 0, async () => { it('removeMemoryCache', 0, async () => {
let a = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp'; let a = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
let option: ImageKnifeOption = new ImageKnifeOption({ let option: ImageKnifeOption = {
loadSrc: 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', loadSrc: 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
signature: '' signature: ''
}) }
let key = ImageKnife.getInstance() let key = ImageKnife.getInstance()
.getEngineKeyImpl() .getEngineKeyImpl()
.generateMemoryKey('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', ImageKnifeRequestSource.SRC, option) .generateMemoryKey('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', ImageKnifeRequestSource.SRC, option)

View File

@ -44,7 +44,7 @@ export default function ImageKnifeOptionTest() {
imageWidth: 0, imageWidth: 0,
imageHeight: 0, imageHeight: 0,
} }
let imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ let ImageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
onLoadListener: { onLoadListener: {
onLoadFailed: (err) => { onLoadFailed: (err) => {
@ -58,10 +58,10 @@ export default function ImageKnifeOptionTest() {
return data; return data;
}, },
}, },
}) }
if (imageKnifeOption.onLoadListener && imageKnifeOption.onLoadListener.onLoadSuccess && imageKnifeOption.onLoadListener.onLoadFailed) { if (ImageKnifeOption.onLoadListener && ImageKnifeOption.onLoadListener.onLoadSuccess && ImageKnifeOption.onLoadListener.onLoadFailed) {
imageKnifeOption.onLoadListener.onLoadSuccess(a,imageData); ImageKnifeOption.onLoadListener.onLoadSuccess(a,imageData);
imageKnifeOption.onLoadListener.onLoadFailed(a); ImageKnifeOption.onLoadListener.onLoadFailed(a);
} }
expect(a).assertEqual(b); expect(a).assertEqual(b);
}); });

View File

@ -18,8 +18,8 @@ import ImageKnifeOptionTest from './ImageKnifeOption.test';
import MemoryLruCacheTest from './MemoryLruCache.test'; import MemoryLruCacheTest from './MemoryLruCache.test';
import ImageKnifeTest from './ImageKnife.test'; import ImageKnifeTest from './ImageKnife.test';
import Transform from './transform.test'; import Transform from './transform.test';
import SamplingTest from './SamplingTest.test';
import imageFormatAndSize from './imageFormatAndSize.test' import imageFormatAndSize from './imageFormatAndSize.test'
import loadCallBackData from './loadCallBackData.test'
export default function testsuite() { export default function testsuite() {
MemoryLruCacheTest(); MemoryLruCacheTest();
@ -28,6 +28,6 @@ export default function testsuite() {
ImageKnifeOptionTest(); ImageKnifeOptionTest();
ImageKnifeTest(); ImageKnifeTest();
Transform(); Transform();
SamplingTest()
imageFormatAndSize(); imageFormatAndSize();
loadCallBackData();
} }

View File

@ -122,9 +122,9 @@ export default function MemoryLruCacheTest() {
it('memoryCacheEngineKey', 0, () => { it('memoryCacheEngineKey', 0, () => {
let engineKey: IEngineKey = new DefaultEngineKey() let engineKey: IEngineKey = new DefaultEngineKey()
let imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ let imageKnifeOption: ImageKnifeOption = {
loadSrc:"abc" loadSrc:"abc"
}) }
let imageKey = engineKey.generateMemoryKey(imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,imageKnifeOption) let imageKey = engineKey.generateMemoryKey(imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,imageKnifeOption)
let imageAnimatorKey = engineKey.generateMemoryKey(imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,imageKnifeOption,true) let imageAnimatorKey = engineKey.generateMemoryKey(imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,imageKnifeOption,true)
expect(imageKey == imageAnimatorKey).assertFalse() expect(imageKey == imageAnimatorKey).assertFalse()

View File

@ -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,)
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)
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_MEMORY)
let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024)
expect(req).assertEqual(true);
})
it('CENTER_OUTSIDE', 3, () => {
let reqSize: calculateScaleType =
new Downsampler().calculateScaling('jpg', 1024, 1024, 200,
200, DownsampleStrategy.CENTER_OUTSIDE_MEMORY)
let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024)
expect(req).assertEqual(true);
})
it('AT_LEAST', 4, () => {
let reqSize: calculateScaleType =
new Downsampler().calculateScaling('jpg', 1024, 1024, 200,
200, DownsampleStrategy.AT_LEAST)
let req = (reqSize.targetWidth < 1024 && reqSize.targetHeight < 1024)
expect(req).assertEqual(true);
})
})
}

View File

@ -1,52 +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 { SendableData } from '@ohos/imageknife/src/main/ets/components/imageknife/SendableData'
export default function SendableDataTest() {
describe('SendableDataTest', ()=> {
// 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('TestPlaceHolderCacheKey', 0, () => {
let value: string = "placeholderRegisterCacheKey";
let data: SendableData = new SendableData();
data.setPlaceHolderRegisterCacheKey(value);
expect(data.getPlaceHolderRegisterCacheKey()).assertEqual(value);
})
it('TestPlaceHolderMemoryCacheKey', 1, () => {
let value: string = "placeholderRegisterMemoryCacheKey";
let data: SendableData = new SendableData();
data.setPlaceHolderRegisterMemoryCacheKey(value);
expect(data.getPlaceHolderRegisterMemoryCacheKey()).assertEqual(value);
})
})
}

View File

@ -1,106 +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 { DownloadClient } from '@ohos/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient';
import common from '@ohos.app.ability.common';
import { GlobalContext } from '../testability/GlobalContext';
import { CustomDataFetchClient, DataFetchResult, ImageKnifeGlobal, RequestOption } from '@ohos/imageknife';
const BASE_COUNT: number = 2000;
export default function CustomDataFetchClientTest() {
describe('CustomDataFetchClientTest', () => {
// 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('TestIsLocalLoadSrc', 0, () => {
let path = 'invalid path';
let client = new DownloadClient()
expect(client.isLocalLoadSrc(undefined, path)).assertFalse();
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
if (context != undefined) {
let loadSrc1 = (context as common.UIAbilityContext).filesDir + 'a.jpg';
let loadSrc2 = (context as common.UIAbilityContext).cacheDir + 'b.jpg';
expect(client.isLocalLoadSrc(context, loadSrc1)).assertTrue();
expect(client.isLocalLoadSrc(context, loadSrc2)).assertTrue();
}
})
it('TestLoadData', 1, async () => {
let client = new CustomDataFetchClient();
let request = new RequestOption();
request.loadSrc = $r('app.media.icon');
let error = (await client.loadData(request) as DataFetchResult).error as String;
expect(error).assertEqual('CustomDataFetchClient request or loadSrc error.');
})
it('TestLoadData_customGetImage', 2, async () => {
let client = new CustomDataFetchClient();
let request = new RequestOption();
request.loadSrc = 'http://e.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e41f5cfe760e0cf3d6cad6ee.jpg';
request.customGetImage = (context: Context, src: string) => {
// 这里是模拟的customGetImage逻辑
return Promise.resolve(new DataFetchResult());
}
console.log('LXH', 'TestLoadData 2 --1 customGetImage is undefined ?' + (request.customGetImage == undefined));
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
let result = await client.loadData(request);
if (context != undefined) {
console.log('LXH', 'TestLoadData 2 --2');
expect(typeof result)
.assertEqual(typeof (await request?.customGetImage(context as common.UIAbilityContext, request.loadSrc)));
}
})
it('TestLoadData_combineArrayBuffers', 3, () => {
// 创建几个ArrayBuffer作为测试数据
const arrayBuffer1 = new ArrayBuffer(4);
const uint8Array1 = new Uint8Array(arrayBuffer1);
uint8Array1[0] = 1;
uint8Array1[1] = 2;
uint8Array1[2] = 3;
uint8Array1[3] = 4;
const arrayBuffer2 = new ArrayBuffer(2);
const uint8Array2 = new Uint8Array(arrayBuffer2);
uint8Array2[0] = 5;
uint8Array2[1] = 6;
let client = new CustomDataFetchClient();
const combinedArrayBuffer = client.combineArrayBuffers([arrayBuffer1, arrayBuffer2]);
expect(combinedArrayBuffer.byteLength).assertEqual(6);
const combinedUint8Array = new Uint8Array(combinedArrayBuffer);
for (let i = 0; i < 4; i++) {
expect(combinedUint8Array[i]).assertEqual(uint8Array1[i]);
}
for (let i = 0; i < 2; i++) {
expect(combinedUint8Array[i + 4]).assertEqual(uint8Array2[i]);
}
});
})
}

View File

@ -49,9 +49,9 @@ export default function imageFormatAndSize() {
let imageFormat: string = ""; let imageFormat: string = "";
let url: string = let url: string =
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg" "https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/ed/v3/KMO4D6D2QGuVOCLX4AhOFA/ef51xAaLQuK7BsnuD9abog.jpg"
let imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ let imageKnifeOption: ImageKnifeOption = {
loadSrc: url, loadSrc: url,
}) }
await new Promise<string>((resolve, reject) => { await new Promise<string>((resolve, reject) => {
imageKnifeOption.onLoadListener = { imageKnifeOption.onLoadListener = {
onLoadSuccess: (data, imageknifeData) => { onLoadSuccess: (data, imageknifeData) => {

View File

@ -1,69 +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 { ImageKnifeOption,ImageKnifeData } from "@ohos/imageknife"
export default function ImageKnifeOptionTest() {
describe('ImageKnifeOptionTest',() => {
// 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('onLoadListener', 0, () => {
let a = 'abc';
let b: string = '';
let imageData:ImageKnifeData = {
source: "",
imageWidth: 0,
imageHeight: 0,
}
let imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({
loadSrc: $r("app.media.rabbit"),
onLoadListener: {
onLoadFailed: (err) => {
console.error("Load Failed Reason: " + err);
},
onLoadSuccess: (data,imageknifeData) => {
if(typeof data == 'string') {
return b = data;
}
imageData = imageknifeData
return data;
},
},
})
if (imageKnifeOption.onLoadListener && imageKnifeOption.onLoadListener.onLoadSuccess && imageKnifeOption.onLoadListener.onLoadFailed) {
imageKnifeOption.onLoadListener.onLoadSuccess(a,imageData);
imageKnifeOption.onLoadListener.onLoadFailed(a);
}
expect(a).assertEqual(b);
});
});
}

View File

@ -0,0 +1,117 @@
/*
* 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 {
ImageKnifeOption,
ImageKnife,
ImageKnifeRequest,
ImageKnifeRequestSource,
CacheStrategy
} from "@ohos/imageknife"
import { common } from '@kit.AbilityKit';
export default function loadCallBackData() {
describe('loadCallBackData', () => {
// 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('startAndSuccess-CallBack', 0, async () => {
let startCallBack: ESObject = undefined;
let successCallBack: ESObject = undefined;
let url: string =
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/63/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg"
let imageKnifeOption: ImageKnifeOption = {
loadSrc: url,
}
await new Promise<string>((resolve, reject) => {
imageKnifeOption.onLoadListener = {
onLoadStart: (data) => {
startCallBack = data?.getImageKnifeData();
},
onLoadSuccess: (data, imageknifeData,req) => {
successCallBack = req?.getImageKnifeData();
resolve("")
},
onLoadFailed(err) {
reject(err)
}
}
let request = new ImageKnifeRequest(
imageKnifeOption,
imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext() as common.UIAbilityContext,
0,
0,
0,
{
showPixelMap(version: number, pixelMap: PixelMap | string) {
}
}
)
ImageKnife.getInstance().execute(request);
})
expect(startCallBack != undefined).assertTrue();
expect(successCallBack != undefined).assertTrue();
});
it('failed-CallBack', 0, async () => {
let failedCallBack: ESObject = undefined;
let url: string =
"https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/163/v3/qbe6NZkCQyGcITvdWoZBgg/Y-5U1z3GT_yaK8CBD3jkwg.jpg"
let imageKnifeOption: ImageKnifeOption = {
loadSrc: url,
}
await new Promise<string>((resolve, reject) => {
imageKnifeOption.onLoadListener = {
onLoadStart: (data) => {
},
onLoadSuccess: (data, imageknifeData) => {
},
onLoadFailed(res,req) {
failedCallBack = req?.getImageKnifeData();
resolve(res)
}
}
let request = new ImageKnifeRequest(
imageKnifeOption,
imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext() as common.UIAbilityContext,
0,
0,
0,
{
showPixelMap(version: number, pixelMap: PixelMap | string) {
}
}
)
ImageKnife.getInstance().execute(request);
})
expect(failedCallBack != undefined).assertTrue();
});
});
}

View File

@ -5,8 +5,9 @@
"description": "$string:module_test_desc", "description": "$string:module_test_desc",
"mainElement": "TestAbility", "mainElement": "TestAbility",
"deviceTypes": [ "deviceTypes": [
"default", "phone",
"tablet" "tablet",
"2in1"
], ],
"deliveryWithInstall": true, "deliveryWithInstall": true,
"installationFree": false, "installationFree": false,

View File

@ -1,10 +1,6 @@
## 1.0.4
- 修改门禁编译问题 修改点如下
- 修改src/main/cpp/boundscheck/CMakeLists.txt文件中的内容
- 修改src/main/cpp/util/DebugLog.h文件中hilog的大小写
## 1.0.3 ## 1.0.3
- 安全编译开启Strip和Ftrapv - 修改门禁编译问题 修改点如下
- 修改src/main/cpp/util/DebugLog.h文件中hilog的大小写
## 1.0.2 ## 1.0.2
- 支持x86编译 - 支持x86编译

View File

@ -3,7 +3,7 @@
"buildOption": { "buildOption": {
"externalNativeOptions": { "externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt", "path": "./src/main/cpp/CMakeLists.txt",
"arguments": " -DCMAKE_BUILD_TYPE=Release", "arguments": "",
"abiFilters": [ "abiFilters": [
"armeabi-v7a", "armeabi-v7a",
"arm64-v8a", "arm64-v8a",

View File

@ -14,7 +14,7 @@
"main": "index.ets", "main": "index.ets",
"repository": "https://gitee.com/openharmony-tpc/ImageKnife", "repository": "https://gitee.com/openharmony-tpc/ImageKnife",
"type": "module", "type": "module",
"version": "1.0.4", "version": "1.0.3",
"tags": [ "tags": [
"Tool" "Tool"
], ],

View File

@ -11,11 +11,8 @@ include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/common ${NATIVERENDER_ROOT_PATH}/common
${NATIVERENDER_ROOT_PATH}/render ${NATIVERENDER_ROOT_PATH}/render
${NATIVERENDER_ROOT_PATH}/constant ${NATIVERENDER_ROOT_PATH}/constant
${NATIVERENDER_ROOT_PATH}/boundscheck
) )
add_subdirectory(boundscheck)
add_library(nativeGpu SHARED add_library(nativeGpu SHARED
${NATIVERENDER_ROOT_PATH}/napi/napi_init.cpp ${NATIVERENDER_ROOT_PATH}/napi/napi_init.cpp
${NATIVERENDER_ROOT_PATH}/render/EGLRender.cpp ${NATIVERENDER_ROOT_PATH}/render/EGLRender.cpp
@ -33,4 +30,4 @@ find_library (
GLES-lib GLES-lib
GLESv3 ) GLESv3 )
target_link_libraries(nativeGpu PUBLIC boundscheck ${hilog-lib} ${EGL-lib} ${GLES-lib} libace_napi.z.so -s -ftrapv) target_link_libraries(nativeGpu PUBLIC ${hilog-lib} ${EGL-lib} ${GLES-lib} libace_napi.z.so libc++.a)

View File

@ -1,27 +0,0 @@
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
set(can_use_assembler TRUE)
enable_language(ASM)
IF("${OHOS_ARCH}" STREQUAL "arm64-v8a")
SET(ASM_OPTIONS "-x assembler-with-cpp")
SET(CMAKE_ASM_FLAGS "${CFLAGS} ${ASM_OPTIONS} -march=armv8+crypto -D__OHOS__")
ENDIF()
project(boundscheck)
set(TAGET_BOUNDSCHECK_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/third_party_bounds_checking_function/src)
add_library(boundscheck
STATIC
${TAGET_BOUNDSCHECK_SRC_PATH}/memcpy_s.c
${TAGET_BOUNDSCHECK_SRC_PATH}/memset_s.c
${TAGET_BOUNDSCHECK_SRC_PATH}/securecutil.c)
target_precompile_headers(boundscheck PUBLIC ${CMAKE_SYSROOT}/usr/include/stdint.h)
include_directories(${TAGET_BOUNDSCHECK_SRC_PATH}
${CMAKE_CURRENT_SOURCE_DIR}/third_party_bounds_checking_function/include
)
target_link_libraries(boundscheck)

@ -1 +0,0 @@
Subproject commit a45b3aceed2c0138babc951850445d1cd010ce48

View File

@ -535,10 +535,7 @@ void EGLRender::SetImageData(uint8_t *pData, int width, int height)
m_RenderImage.height = height; m_RenderImage.height = height;
m_RenderImage.format = IMAGE_FORMAT_RGBA; m_RenderImage.format = IMAGE_FORMAT_RGBA;
NativeImageUtil::AllocNativeImage(&m_RenderImage); NativeImageUtil::AllocNativeImage(&m_RenderImage);
if (memcpy_s(m_RenderImage.ppPlane[0], memcpy(m_RenderImage.ppPlane[0], pData, width * height * DEFAULT_FOUR);
width * height * DEFAULT_FOUR, pData, width * height * DEFAULT_FOUR) != EOK) {
return;
}
glBindTexture(GL_TEXTURE_2D, m_ImageTextureId); glBindTexture(GL_TEXTURE_2D, m_ImageTextureId);
glTexImage2D(GL_TEXTURE_2D, glTexImage2D(GL_TEXTURE_2D,

View File

@ -26,7 +26,6 @@
#include <string> #include <string>
#include <string.h> #include <string.h>
#include "DebugLog.h" #include "DebugLog.h"
#include "third_party_bounds_checking_function/include/securec.h"
const int32_t MAX_STR_LENGTH = 1024; const int32_t MAX_STR_LENGTH = 1024;
@ -42,7 +41,7 @@ void NapiUtil::JsValueToString(const napi_env &env, const napi_value &value, con
LOGI("%s nullptr js object to string malloc failed", __func__); LOGI("%s nullptr js object to string malloc failed", __func__);
return; return;
} }
(void) memset_s(buf.get(), bufLen, 0, bufLen); (void) memset(buf.get(), 0, bufLen);
size_t result = 0; size_t result = 0;
napi_get_value_string_utf8(env, value, buf.get(), bufLen, &result); napi_get_value_string_utf8(env, value, buf.get(), bufLen, &result);
target = buf.get(); target = buf.get();

View File

@ -30,7 +30,6 @@
#include <string.h> #include <string.h>
#include "DebugLog.h" #include "DebugLog.h"
#include "constant/constant_shape.h" #include "constant/constant_shape.h"
#include "third_party_bounds_checking_function/include/securec.h"
#define IMAGE_FORMAT_RGBA 0x01 #define IMAGE_FORMAT_RGBA 0x01
#define IMAGE_FORMAT_NV21 0x02 #define IMAGE_FORMAT_NV21 0x02
@ -49,7 +48,7 @@
#define IMAGE_FORMAT_GRAY_EXT "GRAY" #define IMAGE_FORMAT_GRAY_EXT "GRAY"
#define IMAGE_FORMAT_I444_EXT "I444" #define IMAGE_FORMAT_I444_EXT "I444"
#define IMAGE_FORMAT_P010_EXT "P010" // 16bit NV21 #define IMAGE_FORMAT_P010_EXT "P010" // 16bit NV21
#define EOK 0
struct NativeImage { struct NativeImage {
int width; int width;
@ -141,9 +140,7 @@ public:
if (napi_create_arraybuffer(env, srcLen, &nativePtr, res) != napi_ok || nativePtr == nullptr) { if (napi_create_arraybuffer(env, srcLen, &nativePtr, res) != napi_ok || nativePtr == nullptr) {
return false; return false;
} }
if (memcpy_s(nativePtr, srcLen, src, srcLen) != EOK) { memcpy(nativePtr, src, srcLen);
return false;
}
return true; return true;
} }
@ -152,17 +149,10 @@ public:
int totalLength = width * height * DEFAULT_FOUR; int totalLength = width * height * DEFAULT_FOUR;
int oneLineLength = width * DEFAULT_FOUR; int oneLineLength = width * DEFAULT_FOUR;
uint8_t* tmp = (uint8_t*)malloc(totalLength); uint8_t* tmp = (uint8_t*)malloc(totalLength);
if (memcpy_s(tmp, totalLength, *buf, totalLength) != EOK) { memcpy(tmp, *buf, totalLength);
return; memset(*buf, DEFAULT_ZERO, sizeof(uint8_t)*totalLength);
}
if (memset_s(*buf, sizeof(uint8_t)*totalLength, DEFAULT_ZERO, sizeof(uint8_t)*totalLength) != EOK) {
return;
}
for (int i = 0; i < height; i++) { for (int i = 0; i < height; i++) {
if (memcpy_s(*buf + oneLineLength * i, oneLineLength, memcpy(*buf + oneLineLength * i, tmp + totalLength - oneLineLength * (i+1), oneLineLength);
tmp + totalLength - oneLineLength * (i+1), oneLineLength) != EOK) {
break;
}
} }
free(tmp); free(tmp);
} }

View File

@ -1,7 +1,6 @@
{ {
"hvigorVersion": "4.0.2", "modelVersion": "5.0.0",
"dependencies": { "dependencies": {
"@ohos/hvigor-ohos-plugin": "4.0.2"
}, },
"execution": { "execution": {
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */ // "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */
@ -19,4 +18,4 @@
"nodeOptions": { "nodeOptions": {
// "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */ // "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */
} }
} }

File diff suppressed because one or more lines are too long

48
hvigorw
View File

@ -1,48 +0,0 @@
#!/bin/bash
# ----------------------------------------------------------------------------
# Hvigor startup script, version 1.0.0
#
# Required ENV vars:
# ------------------
# NODE_HOME - location of a Node home dir
# or
# Add /usr/local/nodejs/bin to the PATH environment variable
# ----------------------------------------------------------------------------
HVIGOR_APP_HOME=$(dirname $(readlink -f $0))
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
warn() {
echo ""
echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
}
error() {
echo ""
echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
}
fail() {
error "$@"
exit 1
}
# Determine node to start hvigor wrapper script
if [ -n "${NODE_HOME}" ];then
EXECUTABLE_NODE="${NODE_HOME}/bin/node"
if [ ! -x "$EXECUTABLE_NODE" ];then
fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
fi
else
EXECUTABLE_NODE="node"
which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
fi
# Check hvigor wrapper script
if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
fi
# start hvigor-wrapper script
exec "${EXECUTABLE_NODE}" \
"${HVIGOR_WRAPPER_SCRIPT}" "$@"

View File

@ -1,57 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Hvigor startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
set NODE_EXE=node.exe
goto start
:start
@rem Find node.exe
if defined NODE_HOME goto findNodeFromNodeHome
%NODE_EXE% --version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
echo.
echo Please set the NODE_HOME variable in your environment to match the
echo location of your NodeJs installation.
goto fail
:findNodeFromNodeHome
set NODE_HOME=%NODE_HOME:"=%
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
if exist "%NODE_EXE_PATH%" goto execute
echo.
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
echo.
echo Please set the NODE_HOME variable in your environment to match the
echo location of your NodeJs installation.
goto fail
:execute
@rem Execute hvigor
"%NODE_EXE%" %WRAPPER_MODULE_PATH% %*
:fail
exit /b 1

View File

@ -66,6 +66,4 @@ export { CropTransformation } from './src/main/ets/transform/CropTransformation'
export { MaskTransformation } from './src/main/ets/transform/MaskTransformation' export { MaskTransformation } from './src/main/ets/transform/MaskTransformation'
export { SepiaTransformation } from './src/main/ets/transform/SepiaTransformation' export { SepiaTransformation } from './src/main/ets/transform/SepiaTransformation'
export { DownsampleStrategy } from './src/main/ets/downsampling/DownsampleStartegy'

View File

@ -14,7 +14,7 @@
"main": "index.ets", "main": "index.ets",
"repository": "https://gitee.com/openharmony-tpc/ImageKnife", "repository": "https://gitee.com/openharmony-tpc/ImageKnife",
"type": "module", "type": "module",
"version": "3.1.1-rc.0", "version": "3.2.0-rc.1",
"dependencies": { "dependencies": {
"@ohos/gpu_transform": "^1.0.2" "@ohos/gpu_transform": "^1.0.2"
}, },

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeRequest } from './model/ImageKnifeRequest'; import { ImageKnifeRequest, ImageKnifeRequestState } from './model/ImageKnifeRequest';
import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData'; import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData';
import { MemoryLruCache } from './cache/MemoryLruCache'; import { MemoryLruCache } from './cache/MemoryLruCache';
import { IMemoryCache } from './cache/IMemoryCache' import { IMemoryCache } from './cache/IMemoryCache'
@ -38,7 +38,7 @@ export class ImageKnife {
private _isRequestInSubThread: boolean = true; private _isRequestInSubThread: boolean = true;
//定义全局网络请求header map //定义全局网络请求header map
headerMap: Map<string, Object> = new Map<string, Object>(); headerMap: Map<string, Object> = new Map<string, Object>();
customGetImage: ((context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>) | undefined = undefined customGetImage: ((context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>) => Promise<ArrayBuffer | undefined>) | undefined = undefined
public static getInstance(): ImageKnife { public static getInstance(): ImageKnife {
if (!ImageKnife.instance) { if (!ImageKnife.instance) {
ImageKnife.instance = new ImageKnife(); ImageKnife.instance = new ImageKnife();
@ -80,7 +80,15 @@ export class ImageKnife {
public isFileCacheInit(): boolean { public isFileCacheInit(): boolean {
return this.fileCache === undefined ? false : this.fileCache.isFileCacheInit() return this.fileCache === undefined ? false : this.fileCache.isFileCacheInit()
} }
/**
* 重新加载
*/
reload(request: ImageKnifeRequest) {
if (request.requestState == ImageKnifeRequestState.ERROR) {
request.requestState = ImageKnifeRequestState.PROGRESS
ImageKnife.getInstance().execute(request)
}
}
/** /**
* 全局添加单个请求头header * 全局添加单个请求头header
* @param key 请求头属性 * @param key 请求头属性
@ -137,8 +145,39 @@ export class ImageKnife {
let key = this.getEngineKeyImpl().generateMemoryKey(imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC, imageKnifeOption); let key = this.getEngineKeyImpl().generateMemoryKey(imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC, imageKnifeOption);
this.memoryCache.remove(key); this.memoryCache.remove(key);
} }
/**
* 预加载
* @param loadSrc 图片地址url
* @returns 图片请求request
*/
preload(loadSrc:string | ImageKnifeOption):ImageKnifeRequest{
let imageKnifeOption = new ImageKnifeOption()
if (typeof loadSrc == "string") {
imageKnifeOption.loadSrc = loadSrc
} else {
imageKnifeOption = loadSrc;
}
let request = new ImageKnifeRequest(
imageKnifeOption,
imageKnifeOption.context !== undefined ? imageKnifeOption.context : getContext(this) as common.UIAbilityContext,
0,
0,
0,
{
showPixelMap(version: number, pixelMap: PixelMap | string) {
}
}
)
this.execute(request)
return request
}
/**
* 取消图片请求
* @param request 图片请求request
*/
cancel(request:ImageKnifeRequest) {
request.requestState = ImageKnifeRequestState.DESTROY
}
/** /**
* 预加载图片到文件缓存 * 预加载图片到文件缓存
* @param loadSrc 图片地址url * @param loadSrc 图片地址url
@ -191,10 +230,10 @@ export class ImageKnife {
*/ */
getCacheImage(loadSrc: string, getCacheImage(loadSrc: string,
cacheType: CacheStrategy = CacheStrategy.Default, signature?: string): Promise<ImageKnifeData | undefined> { cacheType: CacheStrategy = CacheStrategy.Default, signature?: string): Promise<ImageKnifeData | undefined> {
let option: ImageKnifeOption = new ImageKnifeOption({ let option: ImageKnifeOption = {
loadSrc: loadSrc, loadSrc: loadSrc,
signature:signature signature:signature
}) }
let engineKeyImpl: IEngineKey = this.getEngineKeyImpl(); let engineKeyImpl: IEngineKey = this.getEngineKeyImpl();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -218,7 +257,7 @@ export class ImageKnife {
*/ */
putCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) { putCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) {
let memoryKey = this.getEngineKeyImpl() let memoryKey = this.getEngineKeyImpl()
.generateMemoryKey(url, ImageKnifeRequestSource.SRC, new ImageKnifeOption({ loadSrc: url, signature: signature })); .generateMemoryKey(url, ImageKnifeRequestSource.SRC, { loadSrc: url, signature: signature });
let fileKey = this.getEngineKeyImpl().generateFileKey(url, signature); let fileKey = this.getEngineKeyImpl().generateFileKey(url, signature);
let imageKnifeData: ImageKnifeData = { source: pixelMap, imageWidth: 0, imageHeight: 0 }; let imageKnifeData: ImageKnifeData = { source: pixelMap, imageWidth: 0, imageHeight: 0 };
switch (cacheType) { switch (cacheType) {
@ -252,9 +291,9 @@ export class ImageKnife {
if (url instanceof ImageKnifeOption) { if (url instanceof ImageKnifeOption) {
imageKnifeOption = url; imageKnifeOption = url;
} else { } else {
imageKnifeOption = new ImageKnifeOption({ imageKnifeOption = {
loadSrc: url loadSrc: url
}); };
} }
let key = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature); let key = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature);
if (this.fileCache !== undefined) { if (this.fileCache !== undefined) {
@ -307,7 +346,7 @@ export class ImageKnife {
* @param cacheType * @param cacheType
* @returns * @returns
*/ */
getCacheUpperLimit(cacheType?: CacheStrategy): number | undefined { getCacheLimitSize(cacheType?: CacheStrategy): number | undefined {
if (cacheType == undefined || cacheType == CacheStrategy.Default) { if (cacheType == undefined || cacheType == CacheStrategy.Default) {
cacheType = CacheStrategy.Memory; cacheType = CacheStrategy.Memory;
} }
@ -327,7 +366,7 @@ export class ImageKnife {
* @param cacheType * @param cacheType
* @returns * @returns
*/ */
getCurrentPicturesNum(cacheType: CacheStrategy): number | undefined { getCurrentCacheNum(cacheType: CacheStrategy): number | undefined {
if (cacheType == undefined || cacheType == CacheStrategy.Default) { if (cacheType == undefined || cacheType == CacheStrategy.Default) {
cacheType = CacheStrategy.Memory; cacheType = CacheStrategy.Memory;
} }
@ -362,7 +401,6 @@ export class ImageKnife {
} }
} }
private pixelMapToArrayBuffer(pixelMap: PixelMap): ArrayBuffer { private pixelMapToArrayBuffer(pixelMap: PixelMap): ArrayBuffer {
let imageInfo = pixelMap.getImageInfoSync(); let imageInfo = pixelMap.getImageInfoSync();
let readBuffer: ArrayBuffer = new ArrayBuffer(imageInfo.size.height * imageInfo.size.width * 4); let readBuffer: ArrayBuffer = new ArrayBuffer(imageInfo.size.height * imageInfo.size.width * 4);
@ -444,10 +482,10 @@ export class ImageKnife {
* 全局设置自定义下载 * 全局设置自定义下载
* @param customGetImage 自定义请求函数 * @param customGetImage 自定义请求函数
*/ */
setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>) { setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>) => Promise<ArrayBuffer | undefined>) {
this.customGetImage = customGetImage this.customGetImage = customGetImage
} }
getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>){ getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>) => Promise<ArrayBuffer | undefined>){
return this.customGetImage return this.customGetImage
} }
} }

View File

@ -19,10 +19,10 @@ import List from '@ohos.util.List';
import LightWeightMap from '@ohos.util.LightWeightMap'; import LightWeightMap from '@ohos.util.LightWeightMap';
import { LogUtil } from './utils/LogUtil'; import { LogUtil } from './utils/LogUtil';
import { ImageKnife } from './ImageKnife'; import { ImageKnife } from './ImageKnife';
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData'; import { ImageKnifeData, CacheStrategy, TimeInfo, ErrorInfo } from './model/ImageKnifeData';
import image from '@ohos.multimedia.image'; import image from '@ohos.multimedia.image';
import emitter from '@ohos.events.emitter'; import emitter from '@ohos.events.emitter';
import { Constants } from './utils/Constants'; import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants';
import taskpool from '@ohos.taskpool'; import taskpool from '@ohos.taskpool';
import { FileTypeUtil } from './utils/FileTypeUtil'; import { FileTypeUtil } from './utils/FileTypeUtil';
import { IEngineKey } from './key/IEngineKey'; import { IEngineKey } from './key/IEngineKey';
@ -35,7 +35,6 @@ import {
} from './model/ImageKnifeData' } from './model/ImageKnifeData'
import { BusinessError } from '@kit.BasicServicesKit'; import { BusinessError } from '@kit.BasicServicesKit';
import { ImageKnifeLoader } from './ImageKnifeLoader' import { ImageKnifeLoader } from './ImageKnifeLoader'
import { DownsampleStrategy } from './downsampling/DownsampleStartegy';
export class ImageKnifeDispatcher { export class ImageKnifeDispatcher {
@ -51,6 +50,7 @@ export class ImageKnifeDispatcher {
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean { showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean {
LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc + "requestSource=" + requestSource + " isAnimator=" + isAnimator) LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc + "requestSource=" + requestSource + " isAnimator=" + isAnimator)
let memoryCache: ImageKnifeData | undefined; let memoryCache: ImageKnifeData | undefined;
let memoryCheckStartTime = Date.now();
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') { if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
memoryCache = { memoryCache = {
source: request.imageKnifeOption.loadSrc as image.PixelMap, source: request.imageKnifeOption.loadSrc as image.PixelMap,
@ -62,23 +62,38 @@ export class ImageKnifeDispatcher {
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator)); .loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
} }
//记录ImageKnifeRequestSource.SRC 开始内存检查的时间点
if (requestSource == ImageKnifeRequestSource.SRC && request.getImageKnifeData()) {
let timeInfo = request.getImageKnifeData()?.timeInfo
if (timeInfo) {
timeInfo.memoryCheckStartTime = memoryCheckStartTime;
timeInfo.memoryCheckEndTime = Date.now();
//设置请求结束的时间点
if (memoryCache !== undefined) {
timeInfo.requestEndTime = Date.now();
}
}
}
if (memoryCache !== undefined) { if (memoryCache !== undefined) {
// 画主图 // 画主图
if (request.requestState === ImageKnifeRequestState.PROGRESS) { if (request.requestState === ImageKnifeRequestState.PROGRESS) {
// 回调请求开始 // 回调请求开始
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
request.imageKnifeOption.onLoadListener.onLoadStart() request.imageKnifeOption.onLoadListener.onLoadStart(request)
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
} }
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, requestSource,memoryCache.imageAnimator) request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source,
{ width: memoryCache.imageWidth, height: memoryCache.imageHeight }, requestSource, memoryCache.imageAnimator)
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.end:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.end:" + request.imageKnifeOption.loadSrc)
if (requestSource == ImageKnifeRequestSource.SRC) { if (requestSource == ImageKnifeRequestSource.SRC) {
request.requestState = ImageKnifeRequestState.COMPLETE request.requestState = ImageKnifeRequestState.COMPLETE
// 回调请求开结束 // 回调请求开结束
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) { if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source,memoryCache) this.copyMemoryCacheInfo(memoryCache, request.getImageKnifeData());
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source, memoryCache, request)
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
} }
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) { } else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
@ -92,8 +107,55 @@ export class ImageKnifeDispatcher {
return false return false
} }
private copyMemoryCacheInfo(memoryCache: ImageKnifeData | undefined, target: ImageKnifeData | undefined) {
if (!memoryCache || !target) {
return;
}
target.source = memoryCache.source;
target.imageWidth = memoryCache.imageWidth;
target.imageHeight = memoryCache.imageHeight;
target.type = memoryCache.type;
target.imageAnimator = memoryCache.imageAnimator;
}
private assembleImageKnifeData(beforeCallData: ImageKnifeData | undefined, afterCallData: ImageKnifeData | undefined, req: ImageKnifeRequest) {
if (!beforeCallData || !afterCallData || !req) {
return;
}
//设置图片开始加载时间及其缓存检查时间点
if (beforeCallData.timeInfo) {
if (afterCallData.timeInfo) {
afterCallData.timeInfo.requestStartTime = beforeCallData.timeInfo.requestStartTime;
afterCallData.timeInfo.memoryCheckStartTime = beforeCallData.timeInfo.memoryCheckStartTime;
afterCallData.timeInfo.memoryCheckEndTime = beforeCallData.timeInfo.memoryCheckEndTime;
}
}
req.setImageKnifeData(afterCallData);
}
private initCallData(request: ImageKnifeRequest) {
if (!request) {
return
}
//图片加载信息回调数据
let callBackData: ImageKnifeData = {
source: "",
imageWidth: 0,
imageHeight: 0,
};
//图片加载信息回调数据时间点
let callBackTimeInfo: TimeInfo = {};
callBackTimeInfo.requestStartTime = Date.now();
callBackData.timeInfo = callBackTimeInfo;
//跟隨請求保存回調信息點
request.setImageKnifeData(callBackData);
}
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void { enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
//初始化加载回调信息
this.initCallData(request);
//1.内存有的话直接渲染 //1.内存有的话直接渲染
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) { if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
return return
@ -105,7 +167,7 @@ export class ImageKnifeDispatcher {
} }
} }
//3.判断是否要排队 //3.判断是否要排队
if (this.executingJobMap.length > this.maxRequests) { if (this.executingJobMap.length >= this.maxRequests) {
this.jobQueue.add(request) this.jobQueue.add(request)
return return
} }
@ -129,6 +191,11 @@ export class ImageKnifeDispatcher {
*/ */
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void { getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void {
LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:" + currentRequest.imageKnifeOption.loadSrc)
if (requestSource === ImageKnifeRequestSource.SRC && currentRequest.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
currentRequest.imageKnifeOption.onLoadListener?.onLoadStart(currentRequest)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc)
}
let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator) let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator)
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey) let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
if (requestList == undefined) { if (requestList == undefined) {
@ -141,11 +208,14 @@ export class ImageKnifeDispatcher {
} }
let isWatchProgress : boolean = false let isWatchProgress : boolean = false
if (currentRequest.imageKnifeOption.progressListener !== undefined && requestSource === ImageKnifeRequestSource.SRC) {
isWatchProgress = true
}
// 回调请求开始 // 回调请求开始
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => { requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) { if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart() requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart(requestWithSource.request)
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc)
} }
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) { if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
@ -184,15 +254,22 @@ export class ImageKnifeDispatcher {
fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(), fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(),
isAnimator:isAnimator, isAnimator:isAnimator,
moduleName: moduleName == "" ? undefined : moduleName, moduleName: moduleName == "" ? undefined : moduleName,
resName: resName == "" ? undefined : resName, resName: resName == "" ? undefined : resName
targetWidth: currentRequest.componentWidth,
targetHeight: currentRequest.componentHeight,
downsampType: currentRequest.imageKnifeOption.downsampleOf==undefined?DownsampleStrategy.NONE:currentRequest.imageKnifeOption.downsampleOf,
} }
if(request.customGetImage == undefined) { if(request.customGetImage == undefined) {
request.customGetImage = ImageKnife.getInstance().getCustomGetImage() request.customGetImage = ImageKnife.getInstance().getCustomGetImage()
} }
emitter.on(Constants.CALLBACK_EMITTER + memoryKey,(data)=>{
emitter.off(Constants.CALLBACK_EMITTER + memoryKey)
let res = data?.data?.value as RequestJobResult | undefined
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
if (isWatchProgress){
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
}
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
})
if (ImageKnife.getInstance().isRequestInSubThread){ if (ImageKnife.getInstance().isRequestInSubThread){
// 启动线程下载和解码主图 // 启动线程下载和解码主图
LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:" + currentRequest.imageKnifeOption.loadSrc)
@ -206,13 +283,14 @@ export class ImageKnifeDispatcher {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(subthread):" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(subthread):" + currentRequest.imageKnifeOption.loadSrc)
taskpool.execute(task).then((res: Object) => { taskpool.execute(task).then((res: Object) => {
this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator); // this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
if (isWatchProgress){ // if (isWatchProgress){
emitter.off(Constants.PROGRESS_EMITTER + memoryKey) // emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
} // }
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc) // LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc) // LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
}).catch((err: BusinessError) => { }).catch((err: BusinessError) => {
emitter.off(Constants.CALLBACK_EMITTER + memoryKey)
LogUtil.error("Fail to requestJob in sub thread src=" + imageSrc + " err=" + err) LogUtil.error("Fail to requestJob in sub thread src=" + imageSrc + " err=" + err)
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc)
if (isWatchProgress){ if (isWatchProgress){
@ -223,11 +301,12 @@ export class ImageKnifeDispatcher {
}) })
} else { //主线程请求 } else { //主线程请求
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):" + currentRequest.imageKnifeOption.loadSrc)
requestJob(request, requestList).then((res: RequestJobResult | undefined) => { requestJob(request, requestList).then(() => {
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator); // this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc) // LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc) // LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
}).catch((err: BusinessError) => { }).catch((err: BusinessError) => {
emitter.off(Constants.CALLBACK_EMITTER + memoryKey)
LogUtil.error("Fail to requestJob in main thread src=" + imageSrc + " err=" + err) LogUtil.error("Fail to requestJob in main thread src=" + imageSrc + " err=" + err)
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc)
this.executingJobMap.remove(memoryKey); this.executingJobMap.remove(memoryKey);
@ -256,6 +335,12 @@ export class ImageKnifeDispatcher {
if (requestJobResult === undefined){ if (requestJobResult === undefined){
return return
} }
//设置请求结束的时间
if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) {
requestJobResult.imageKnifeData.timeInfo.requestEndTime = Date.now();
}
let pixelmap = requestJobResult.pixelMap; let pixelmap = requestJobResult.pixelMap;
if (pixelmap === undefined) { if (pixelmap === undefined) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc)
@ -264,7 +349,8 @@ export class ImageKnifeDispatcher {
if (requestWithSource.source === ImageKnifeRequestSource.SRC && if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined &&
requestJobResult.loadFail) { requestJobResult.loadFail) {
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail); this.assembleImageKnifeData(requestWithSource.request.getImageKnifeData(), requestJobResult.imageKnifeData, requestWithSource.request)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc)
} }
if (requestWithSource.source === ImageKnifeRequestSource.SRC && if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
@ -288,12 +374,19 @@ export class ImageKnifeDispatcher {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc)
} }
let ImageKnifeData: ImageKnifeData = { let imageKnifeData: ImageKnifeData;
source: pixelmap!, if (!requestJobResult.imageKnifeData) {
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width, imageKnifeData = {
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height, source: pixelmap!,
type:requestJobResult.type imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
}; imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
type: requestJobResult.type,
};
} else {
imageKnifeData = requestJobResult.imageKnifeData;
imageKnifeData.source = pixelmap!;
}
if(requestJobResult.pixelMapList != undefined) { if(requestJobResult.pixelMapList != undefined) {
let imageAnimator: Array<ImageFrameInfo> = [] let imageAnimator: Array<ImageFrameInfo> = []
requestJobResult.pixelMapList.forEach((item,index)=>{ requestJobResult.pixelMapList.forEach((item,index)=>{
@ -302,14 +395,24 @@ export class ImageKnifeDispatcher {
duration:requestJobResult.delayList![index] duration:requestJobResult.delayList![index]
}) })
}) })
ImageKnifeData.imageAnimator = imageAnimator imageKnifeData.imageAnimator = imageAnimator
} }
//构建缓存保存的ImageKnifeData
let saveCacheImageData: ImageKnifeData = {
source: pixelmap!,
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
type: requestJobResult.type,
imageAnimator: imageKnifeData.imageAnimator
}
// 保存内存缓存 // 保存内存缓存
if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) { if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc)
ImageKnife.getInstance() ImageKnife.getInstance()
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator), .saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator),
ImageKnifeData); saveCacheImageData);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
} }
if (requestList !== undefined) { if (requestList !== undefined) {
@ -323,7 +426,8 @@ export class ImageKnifeDispatcher {
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) { requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc)
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion, requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
ImageKnifeData.source, requestWithSource.source,ImageKnifeData.imageAnimator); imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight },
requestWithSource.source, imageKnifeData.imageAnimator);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc)
} }
@ -332,7 +436,9 @@ export class ImageKnifeDispatcher {
if (requestWithSource.request.imageKnifeOption.onLoadListener && if (requestWithSource.request.imageKnifeOption.onLoadListener &&
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) { requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
// 回调请求成功 // 回调请求成功
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(ImageKnifeData.source,ImageKnifeData); this.assembleImageKnifeData(requestWithSource.request.getImageKnifeData(), imageKnifeData,requestWithSource.request);
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source,
saveCacheImageData, requestWithSource.request);
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc)
} }
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) { } else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
@ -341,7 +447,19 @@ export class ImageKnifeDispatcher {
} else { } else {
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) { if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
// 回调请求成功 // 回调请求成功
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") // 回调请求成功
//设置失败回调的时间点
let callBackData = requestWithSource.request.getImageKnifeData();
if (requestJobResult.imageKnifeData && requestJobResult.imageKnifeData.timeInfo) {
requestJobResult.imageKnifeData.timeInfo.requestCancelTime = Date.now();
if (requestJobResult.imageKnifeData.errorInfo) {
requestJobResult.imageKnifeData.errorInfo.phase = LoadPhase.PHASE_WILL_SHOW;
requestJobResult.imageKnifeData.errorInfo.code = LoadPixelMapCode.IMAGE_LOAD_CANCEL_FAILED_CODE;
}
}
this.assembleImageKnifeData(callBackData,requestJobResult.imageKnifeData,requestWithSource.request)
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed", requestWithSource.request)
} }
} }
}); });
@ -369,7 +487,19 @@ export class ImageKnifeDispatcher {
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc)
break break
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) { }else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed") //构建回调错误信息
let callBackData = request.getImageKnifeData();
if (callBackData) {
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData)
timeInfo.requestCancelTime = Date.now();
timeInfo.requestEndTime = Date.now()
let errorInfo: ErrorInfo = {
phase: LoadPhase.PHASE_THREAD_QUEUE,
code: LoadPixelMapCode.IMAGE_LOAD_CANCEL_FAILED_CODE,
};
callBackData.errorInfo = errorInfo;
}
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed", request)
} }
} }
} }
@ -396,44 +526,15 @@ export class ImageKnifeDispatcher {
* @returns * @returns
*/ */
@Concurrent @Concurrent
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>): Promise<RequestJobResult | undefined> { async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>) {
LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src + " requestSource=" + request.requestSource) LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src + " requestSource=" + request.requestSource)
let src = typeof request.src == "number" ? request.resName != undefined ? request.resName : request.src + "" : request.src let src = typeof request.src == "number" ? request.resName != undefined ? request.resName : request.src + "" : request.src
// 生成文件缓存key // 生成文件缓存key
let fileKey = request.engineKey.generateFileKey(src, request.signature, request.isAnimator) let fileKey = request.engineKey.generateFileKey(src, request.signature, request.isAnimator)
//获取图片资源 //获取图片资源
let resBuf: ArrayBuffer ImageKnifeLoader.execute(request,requestList,fileKey)
try {
LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.start:" + request.src)
resBuf = await ImageKnifeLoader.getImageArrayBuffer(request, requestList, fileKey)
LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.end:" + request.src)
} catch (error) {
LogUtil.error("ImageKnife_DataTime_requestJob.end: getImageArrayBuffer error " + request.src + " err=" + error)
return ImageKnifeLoader.makeEmptyResult(error)
}
// 获取图片类型
let typeValue = new FileTypeUtil().getFileType(resBuf);
if(typeValue == null) {
LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src)
return ImageKnifeLoader.makeEmptyResult("request is not a valid image source")
}
// 解析图片
LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.start:" + request.src)
let result: RequestJobResult = await ImageKnifeLoader.parseImage(resBuf, typeValue, fileKey, request)
LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.end:" + request.src)
// 图形变化
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && result?.pixelMap !== undefined && typeof result.pixelMap !== 'string') {
LogUtil.log("ImageKnife_DataTime_requestJob.transform.start:" + request.src)
result.pixelMap = await request.transformation?.transform(request.context, result.pixelMap, request.componentWidth, request.componentHeight);
LogUtil.log("ImageKnife_DataTime_requestJob.transform.end:" + request.src)
}
LogUtil.log("ImageKnife_DataTime_requestJob.end:" + request.src)
return result
} }

View File

@ -14,12 +14,16 @@
*/ */
import { import {
CacheStrategy, CacheStrategy,
DecodeImageInfo,
ErrorInfo,
ImageKnifeData,
ImageKnifeRequestSource, ImageKnifeRequestSource,
ImageKnifeRequestWithSource, RequestJobRequest } from './model/ImageKnifeData'; ImageKnifeRequestWithSource, RequestJobRequest,
TimeInfo } from './model/ImageKnifeData';
import List from '@ohos.util.List' import List from '@ohos.util.List'
import { FileCache } from './cache/FileCache'; import { FileCache } from './cache/FileCache';
import { LogUtil } from './utils/LogUtil'; import { LogUtil } from './utils/LogUtil';
import { Constants } from './utils/Constants'; import { Constants, LoadPhase, LoadPixelMapCode } from './utils/Constants';
import http from '@ohos.net.http'; import http from '@ohos.net.http';
import { combineArrayBuffers } from './utils/ArrayBufferUtils'; import { combineArrayBuffers } from './utils/ArrayBufferUtils';
import { BusinessError } from '@kit.BasicServicesKit'; import { BusinessError } from '@kit.BasicServicesKit';
@ -28,8 +32,7 @@ import emitter from '@ohos.events.emitter';
import image from '@ohos.multimedia.image'; import image from '@ohos.multimedia.image';
import { RequestJobResult } from './model/ImageKnifeData' import { RequestJobResult } from './model/ImageKnifeData'
import util from '@ohos.util'; import util from '@ohos.util';
import { DownsampleStrategy } from './downsampling/DownsampleStartegy'; import { FileTypeUtil } from './utils/FileTypeUtil';
import { Downsampler } from './downsampling/Downsampler';
class RequestData { class RequestData {
receiveSize: number = 2000 receiveSize: number = 2000
@ -40,79 +43,152 @@ class RequestData {
* ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法故抽取到另一个类 * ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法故抽取到另一个类
*/ */
export class ImageKnifeLoader { export class ImageKnifeLoader {
static async parseImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, static execute(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined, fileKey: string){
request: RequestJobRequest): Promise<RequestJobResult> { ImageKnifeLoader.getImageArrayBuffer(request,requestList,fileKey)
}
static async parseImage(resBuf: ArrayBuffer, fileKey: string,
request: RequestJobRequest, callBackData: ImageKnifeData) {
callBackData.bufSize = resBuf.byteLength;
let typeValue = new FileTypeUtil().getFileType(resBuf);
if(typeValue == null) {
LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src)
ImageKnifeLoader.makeEmptyResult(request,"request is not a valid image source", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT, LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE))
return
}
callBackData.type = typeValue;
if(request.isAnimator) { if(request.isAnimator) {
return ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request) ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request, callBackData)
return
} }
if (typeValue === 'gif' || typeValue === 'webp') { if (typeValue === 'gif' || typeValue === 'webp') {
return ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request) ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request, callBackData)
return
} else if(typeValue == "svg") { } else if(typeValue == "svg") {
return ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request) ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request, callBackData)
return
} }
return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request) ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request, callBackData)
} }
static makeEmptyResult(error: string): RequestJobResult{ static makeEmptyResult(request:RequestJobRequest,error: string, data?: ImageKnifeData){
return { let res: RequestJobResult = {
pixelMap: undefined, pixelMap: undefined,
bufferSize: 0, bufferSize: 0,
fileKey: '', fileKey: '',
loadFail: error, loadFail: error,
imageKnifeData: data
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} }
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest):Promise<RequestJobResult> { static assembleError(data: ImageKnifeData | undefined, phase: string, code?: number,
httpCode?: number): ImageKnifeData | undefined {
let errorCallBackData = data?.errorInfo;
if (!errorCallBackData) {
return data;
}
errorCallBackData.phase = phase;
errorCallBackData.code = code? code: 0;
if (httpCode && httpCode != 0) {
errorCallBackData.httpCode = httpCode;
}
return data
}
static getTimeInfo(callBackData: ImageKnifeData): TimeInfo {
let timeInfo: TimeInfo;
if (callBackData.timeInfo) {
timeInfo = callBackData.timeInfo;
}else {
timeInfo = {};
callBackData.timeInfo = timeInfo;
}
return timeInfo;
}
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest, callBackData: ImageKnifeData) {
let resPixelmap: PixelMap | undefined = undefined let resPixelmap: PixelMap | undefined = undefined
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
let decodingOptions: image.DecodingOptions = { let decodingOptions: image.DecodingOptions = {
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false, editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
} }
let imageSource: image.ImageSource = image.createImageSource(resBuf) let imageSource: image.ImageSource = image.createImageSource(resBuf)
if (imageSource === undefined){ if (imageSource === undefined){
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return
} }
let size = (await imageSource.getImageInfo()).size let size = (await imageSource.getImageInfo()).size
try { callBackData.imageWidth = size.width;
if ((request.downsampType !== DownsampleStrategy.NONE) && callBackData.imageHeight = size.height;
request.requestSource == ImageKnifeRequestSource.SRC) { timeInfo.decodeStartTime = Date.now();
decodingOptions = ImageKnifeLoader.getDownsamplerDecodingOptions(typeValue, request, size, ImageKnifeRequestSource.SRC)
}
} catch (err) {
return ImageKnifeLoader.makeEmptyResult(err)
}
await imageSource.createPixelMap(decodingOptions) await imageSource.createPixelMap(decodingOptions)
.then((pixelmap: PixelMap) => { .then((pixelmap: PixelMap) => {
timeInfo.decodeEndTime = Date.now();
resPixelmap = pixelmap resPixelmap = pixelmap
imageSource.release() imageSource.release()
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
timeInfo.decodeEndTime = Date.now();
imageSource.release() imageSource.release()
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error)) ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_PIXEL_MAP, LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE))
return
}) })
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) {
LogUtil.log("ImageKnife_DataTime_requestJob.transform.start:" + request.src)
resPixelmap = await request.transformation?.transform(request.context, resPixelmap, request.componentWidth, request.componentHeight);
LogUtil.log("ImageKnife_DataTime_requestJob.transform.end:" + request.src)
}
try {
resPixelmap?.setTransferDetached(true)
} catch (e) {
LogUtil.error("PixelMap setTransferDetached err:"+JSON.stringify(e))
}
return { //获取各个pixelMap的大小
if (resPixelmap && typeof resPixelmap !== "string") {
let decodeImages: Array<DecodeImageInfo> = [];
let size = (resPixelmap as PixelMap).getImageInfoSync().size;
let decodeImage: DecodeImageInfo = {
contentWidth: size.width,
contentHeight: size.height,
contentSize: (resPixelmap as PixelMap).getPixelBytesNumber()
}
decodeImages.push(decodeImage);
callBackData.decodeImages = decodeImages;
}
let res: RequestJobResult = {
pixelMap: resPixelmap, pixelMap: resPixelmap,
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
size:size, size:size,
type:typeValue type:typeValue,
}; imageKnifeData:callBackData
}
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} }
static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
request: RequestJobRequest): Promise<RequestJobResult> { request: RequestJobRequest, callBackData: ImageKnifeData) {
let resPixelmap: PixelMap | undefined = undefined let resPixelmap: PixelMap | undefined = undefined
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
let imageSource: image.ImageSource = image.createImageSource(resBuf) let imageSource: image.ImageSource = image.createImageSource(resBuf)
if (imageSource === undefined){ if (imageSource === undefined){
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return
} }
let size = (await imageSource.getImageInfo()).size let size = (await imageSource.getImageInfo()).size
let scale = size.height / size.width let scale = size.height / size.width
let hValue = Math.round(request.componentHeight); let hValue = Math.round(request.componentHeight);
let wValue = Math.round(request.componentWidth); let wValue = Math.round(request.componentWidth);
callBackData.imageWidth = size.width;
callBackData.imageHeight = size.height;
timeInfo.decodeStartTime = Date.now();
let defaultSize: image.Size = { let defaultSize: image.Size = {
height: vp2px(wValue) * scale, height: vp2px(wValue) * scale,
width: vp2px(wValue) width: vp2px(wValue)
@ -121,67 +197,99 @@ export class ImageKnifeLoader {
editable: true, editable: true,
desiredSize: defaultSize desiredSize: defaultSize
}; };
try {
if ((request.downsampType !== DownsampleStrategy.NONE) &&
request.requestSource == ImageKnifeRequestSource.SRC) {
opts = ImageKnifeLoader.getDownsamplerDecodingOptions(typeValue, request, size)
}
} catch (err) {
return ImageKnifeLoader.makeEmptyResult(err)
}
await imageSource.createPixelMap(opts) await imageSource.createPixelMap(opts)
.then((pixelmap: PixelMap) => { .then((pixelmap: PixelMap) => {
timeInfo.decodeEndTime = Date.now();
resPixelmap = pixelmap resPixelmap = pixelmap
imageSource.release() imageSource.release()
try {
resPixelmap.setTransferDetached(true)
} catch (e) {
LogUtil.error("PixelMap setTransferDetached err:"+JSON.stringify(e))
}
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
timeInfo.decodeEndTime = Date.now();
imageSource.release() imageSource.release()
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error)) ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_PIXEL_MAP, LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE))
return
}) })
return { //获取各个pixelMap的大小
if (resPixelmap && typeof resPixelmap !== "string") {
let decodeImages: Array<DecodeImageInfo> = [];
let decodeImage: DecodeImageInfo = {
contentWidth: defaultSize.width,
contentHeight: defaultSize.height,
contentSize: (resPixelmap as PixelMap).getPixelBytesNumber()
}
decodeImages.push(decodeImage);
}
let res: RequestJobResult = {
pixelMap: resPixelmap, pixelMap: resPixelmap,
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
type:typeValue type:typeValue,
}; imageKnifeData:callBackData
}
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} }
static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string, static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string,
fileKey: string,request: RequestJobRequest): Promise<RequestJobResult> { fileKey: string,request: RequestJobRequest, callBackData: ImageKnifeData) {
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
let imageSource: image.ImageSource = image.createImageSource(resBuf) let imageSource: image.ImageSource = image.createImageSource(resBuf)
if (imageSource === undefined){ if (imageSource === undefined){
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CREATE_SOURCE,LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return
} }
let frameCount = await imageSource.getFrameCount() let frameCount = await imageSource.getFrameCount()
let size = (await imageSource.getImageInfo()).size let size = (await imageSource.getImageInfo()).size
callBackData.frameCount = frameCount;
callBackData.imageWidth = size.width;
callBackData.imageHeight = size.height;
imageSource.release() imageSource.release()
if(frameCount == undefined || frameCount == 1) { if(frameCount == undefined || frameCount == 1) {
} else { } else {
timeInfo.decodeStartTime = Date.now()
let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf)) let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf))
return { timeInfo.diskCheckEndTime = Date.now()
let res: RequestJobResult = {
pixelMap: base64str, pixelMap: base64str,
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
size:size, size:size,
type:typeValue type:typeValue,
}; imageKnifeData:callBackData
}
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
return
} }
return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request) ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request, callBackData)
} }
// 为AnimatorComponent解析动图 // 为AnimatorComponent解析动图
static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest): Promise<RequestJobResult> { static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest, callBackData: ImageKnifeData) {
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
if (typeValue === 'gif' || typeValue === 'webp') { if (typeValue === 'gif' || typeValue === 'webp') {
let imageSource: image.ImageSource = image.createImageSource(resBuf); let imageSource: image.ImageSource = image.createImageSource(resBuf);
if (imageSource === undefined){ if (imageSource === undefined){
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed") ImageKnifeLoader.makeEmptyResult(request,"image.createImageSource failed", ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CREATE_SOURCE, LoadPixelMapCode.IMAGE_SOURCE_ERROR_CODE))
return
} }
let decodingOptions: image.DecodingOptions = { let decodingOptions: image.DecodingOptions = {
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false, editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
} }
callBackData.imageWidth = imageSource.getImageInfoSync().size.width;
callBackData.imageHeight = imageSource.getImageInfoSync().size.height;
let pixelMapList: Array<PixelMap> = [] let pixelMapList: Array<PixelMap> = []
let delayList: Array<number> = [] let delayList: Array<number> = []
timeInfo.decodeStartTime = Date.now();
let decodeImages: Array<DecodeImageInfo> = [];
await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => { await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => {
timeInfo.decodeEndTime = Date.now();
//sdk的api接口发生变更从.getDelayTime() 变为.getDelayTimeList() //sdk的api接口发生变更从.getDelayTime() 变为.getDelayTimeList()
await imageSource.getDelayTimeList().then(delayTimes => { await imageSource.getDelayTimeList().then(delayTimes => {
if (pixelList.length > 0) { if (pixelList.length > 0) {
@ -192,77 +300,126 @@ export class ImageKnifeLoader {
} else { } else {
delayList.push(delayTimes[delayTimes.length - 1]) delayList.push(delayTimes[delayTimes.length - 1])
} }
//获取各个pixelMap的大小
let size = pixelList[i].getImageInfoSync().size
let decodeImage: DecodeImageInfo = {
contentWidth: size.width,
contentHeight: size.height,
contentSize: pixelList[i].getPixelBytesNumber()
}
decodeImages.push(decodeImage);
} }
imageSource.release(); imageSource.release();
} }
}) })
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
imageSource.release() imageSource.release()
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error)) timeInfo.decodeEndTime = Date.now();
ImageKnifeLoader.makeEmptyResult(request,JSON.stringify(error), ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CREATE_PIXEL_MAP,LoadPixelMapCode.IMAGE_DECODE_ERROR_CODE))
return
}) })
return { callBackData.decodeImages = decodeImages;
let res: RequestJobResult = {
pixelMap: "", pixelMap: "",
bufferSize: resBuf.byteLength, bufferSize: resBuf.byteLength,
fileKey: fileKey, fileKey: fileKey,
type: typeValue, type: typeValue,
imageKnifeData:callBackData,
pixelMapList, pixelMapList,
delayList delayList
} }
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { "value": res } })
} else { } else {
return ImageKnifeLoader.makeEmptyResult("ImageKnifeAnimatorComponent组件仅支持动态图") ImageKnifeLoader.makeEmptyResult(request,"ImageKnifeAnimatorComponent组件仅支持动态图", ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_PARSE_IAMGE,LoadPixelMapCode.IMAGE_FORMAT_ERROR_CODE))
} }
} }
static getHeaderObj(request:RequestJobRequest){
const headerObj: Record<string, Object> = {}
if (request.headers != undefined) {
request.headers.forEach((value) => {
headerObj[value.key] = value.value
})
} else if (request.allHeaders.size > 0) {
request.allHeaders.forEach((value, key) => {
headerObj[key] = value
})
}
return headerObj
}
static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string, callBackData: ImageKnifeData){
// 保存文件缓存
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
}
ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
}
// 获取图片资源 // 获取图片资源
static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string): Promise<ArrayBuffer> { static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string) {
let resBuf: ArrayBuffer | undefined let resBuf: ArrayBuffer | undefined
let loadError: string = ""
//定义图片各个阶段错误信息
let error: ErrorInfo = { code: 0, phase: LoadPhase.PHASE_LOAD }
//定义加载时间点
let callBackTimeInfo: TimeInfo = {};
//定义加载信息回调数据
let callBackData: ImageKnifeData = {
source: "",
imageWidth: 0,
imageHeight: 0,
timeInfo: callBackTimeInfo,
errorInfo: error
};
// 判断自定义下载 // 判断自定义下载
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") { if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") {
// 先从文件缓存获取 // 先从文件缓存获取
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CUSTOM_LOAD)
callBackTimeInfo.diskCheckStartTime = Date.now();
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
callBackTimeInfo.diskCheckEndTime = Date.now();
if (resBuf === undefined) { if (resBuf === undefined) {
LogUtil.log("start customGetImage src=" + request.src) LogUtil.log("start customGetImage src=" + request.src)
const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request)
try { try {
resBuf = await request.customGetImage(request.context, request.src) request.customGetImage(request.context, request.src, headerObj)
LogUtil.log("end customGetImage src=" + request.src) .then((buffer)=>{
} catch (err) { if(buffer != undefined) {
throw new Error('customGetImage loadFile failed! err = ' + err) ImageKnifeLoader.FileCacheParseImage(request,buffer,fileKey,callBackData)
} } else {
if (resBuf === undefined) { loadError = "customGetImage loadFail undefined"
throw new Error('customGetImage loadFile failed!') ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
} }
// 保存文件缓存 }).catch((err:string)=>{
if (request.writeCacheStrategy !== CacheStrategy.Memory) { ImageKnifeLoader.makeEmptyResult(request,err, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:" + request.src) })
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf, request.fileCacheFolder) } catch (e) {
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:" + request.src) loadError = "customGetImage loadFail failed"
ImageKnifeLoader.makeEmptyResult(request,loadError + e, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
} }
LogUtil.log("end customGetImage src=" + request.src)
return
} }
} }
else { else {
if (typeof request.src === 'string') { if (typeof request.src === 'string') {
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载 if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
// 先从文件缓存获取 // 先从文件缓存获取
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET)
callBackTimeInfo.diskCheckStartTime = Date.now()
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder) resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
callBackTimeInfo.diskCheckEndTime = Date.now()
if (resBuf !== undefined){ if (resBuf !== undefined){
LogUtil.log("success get image from filecache for key = " + fileKey + " src = " + request.src) LogUtil.log("success get image from filecache for key = " + fileKey + " src = " + request.src)
} }
else if (request.onlyRetrieveFromCache != true) { else if (request.onlyRetrieveFromCache != true) {
LogUtil.log("HttpDownloadClient.start:" + request.src) LogUtil.log("HttpDownloadClient.start:" + request.src)
callBackTimeInfo.netRequestStartTime = Date.now();
let httpRequest = http.createHttp(); let httpRequest = http.createHttp();
let progress: number = 0 let progress: number = 0
let arrayBuffers = new Array<ArrayBuffer>() let arrayBuffers = new Array<ArrayBuffer>()
const headerObj: Record<string, object> = {} const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request)
if (request.headers != undefined) {
request.headers.forEach((value) => {
headerObj[value.key] = value.value
})
} else if (request.allHeaders.size > 0) {
request.allHeaders.forEach((value, key) => {
headerObj[key] = value
})
}
httpRequest.on("dataReceive", (data: ArrayBuffer) => { httpRequest.on("dataReceive", (data: ArrayBuffer) => {
arrayBuffers.push(data) arrayBuffers.push(data)
}); });
@ -299,27 +456,30 @@ export class ImageKnifeLoader {
// header: new Header('application/json') // header: new Header('application/json')
}); });
await promise.then((data: number) => { promise.then((data: number) => {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, undefined, data)
callBackTimeInfo.netRequestEndTime = Date.now();
if (data == 200 || data == 206 || data == 204) { if (data == 200 || data == 206 || data == 204) {
resBuf = combineArrayBuffers(arrayBuffers) resBuf = combineArrayBuffers(arrayBuffers)
ImageKnifeLoader.FileCacheParseImage(request,resBuf,fileKey, callBackData)
} else { } else {
throw new Error("HttpDownloadClient has error, http code =" + JSON.stringify(data)) loadError = "HttpDownloadClient has error, http code =" + JSON.stringify(data)
ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE, data))
} }
}).catch((err: Error) => { }).catch((err: Error) => {
throw new Error("HttpDownloadClient download ERROR : err = " + JSON.stringify(err)) loadError = "HttpDownloadClient download ERROR : err = " + JSON.stringify(err)
callBackTimeInfo.netRequestEndTime = Date.now();
ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, LoadPixelMapCode.IMAGE_HTTPS_LOAD_FAILED_CODE, undefined))
}); });
LogUtil.log("HttpDownloadClient.end:" + request.src) LogUtil.log("HttpDownloadClient.end:" + request.src)
// 保存文件缓存 return
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
}
} }
else { else {
throw new Error('onlyRetrieveFromCache,do not fetch image src = ' + request.src) callBackTimeInfo.netRequestEndTime = Date.now();
loadError = 'onlyRetrieveFromCache,do not fetch image src = ' + request.src
} }
} else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) { } else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) {
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE)
await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => { await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => {
await fs.stat(file.fd).then(async (stat) =>{ await fs.stat(file.fd).then(async (stat) =>{
let buf = new ArrayBuffer(stat.size); let buf = new ArrayBuffer(stat.size);
@ -327,15 +487,19 @@ export class ImageKnifeLoader {
resBuf = buf; resBuf = buf;
fs.closeSync(file.fd); fs.closeSync(file.fd);
}).catch((err:BusinessError) => { }).catch((err:BusinessError) => {
throw new Error('LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code) ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE)
loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code
}) })
}).catch((err:BusinessError) => { }).catch((err:BusinessError) => {
throw new Error('LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code) ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE)
loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code
}) })
}).catch((err:BusinessError) => { }).catch((err:BusinessError) => {
throw new Error('LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code) ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_SHARE_FILE, LoadPixelMapCode.IMAGE_LOAD_SHARE_FILE_FAILED_CODE)
loadError = 'LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code
}) })
} else { //从本地文件获取 } else { //从本地文件获取
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE)
try { try {
let stat = fs.statSync(request.src); let stat = fs.statSync(request.src);
if (stat.size > 0) { if (stat.size > 0) {
@ -345,7 +509,8 @@ export class ImageKnifeLoader {
fs.closeSync(file); fs.closeSync(file);
} }
} catch (err) { } catch (err) {
throw new Error(err) ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE, LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE)
loadError = err
} }
} }
} else if (typeof request.src == "number") { //从资源文件获取 } else if (typeof request.src == "number") { //从资源文件获取
@ -369,34 +534,10 @@ export class ImageKnifeLoader {
} }
if (resBuf === undefined){ if (resBuf === undefined){
throw new Error('getImageArrayBuffer undefined') callBackTimeInfo.requestEndTime = Date.now();
ImageKnifeLoader.makeEmptyResult(request,loadError ,callBackData)
return
} }
return resBuf ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
} }
}
static getDownsamplerDecodingOptions(typeValue: string, request: RequestJobRequest, size: Size,
SRC?: ImageKnifeRequestSource):image.DecodingOptions {
let reqSize =
new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth, request.targetHeight,
request.downsampType)
if (typeValue == "svg") {
return {
editable: true,
desiredSize: {
height: vp2px(reqSize.height),
width: vp2px(reqSize.width)
}
}
} else {
return {
editable: request.requestSource === SRC && request.transformation !== undefined ? true : false,
desiredSize:{
width: reqSize.width,
height: reqSize.height
}
}
}
}
}

View File

@ -19,14 +19,15 @@ import { ImageKnife } from '../ImageKnife';
import { LogUtil } from '../utils/LogUtil'; import { LogUtil } from '../utils/LogUtil';
import { ImageKnifeRequestSource } from '../model/ImageKnifeData'; import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
@ComponentV2 @Component
export struct ImageKnifeAnimatorComponent { export struct ImageKnifeAnimatorComponent {
@Param animatorOption: AnimatorOption = new AnimatorOption(); @Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
@Local pixelMap: PixelMap | string | undefined = undefined @State animatorOption: AnimatorOption = new AnimatorOption();
@Local imageAnimator: Array<ImageFrameInfo> | undefined = undefined @State pixelMap: PixelMap | string | undefined = undefined
@Local adaptiveWidth: Length = '100%' @State imageAnimator: Array<ImageFrameInfo> | undefined = undefined
@Local adaptiveHeight: Length = '100%' @State adaptiveWidth: Length = '100%'
@Local objectFit: ImageFit = ImageFit.Contain @State adaptiveHeight: Length = '100%'
@State objectFit: ImageFit = ImageFit.Contain
private request: ImageKnifeRequest | undefined private request: ImageKnifeRequest | undefined
private lastWidth: number = 0 private lastWidth: number = 0
private lastHeight: number = 0 private lastHeight: number = 0
@ -34,17 +35,7 @@ export struct ImageKnifeAnimatorComponent {
private currentHeight: number = 0 private currentHeight: number = 0
private componentVersion: number = 0 private componentVersion: number = 0
private currentContext: common.UIAbilityContext | undefined = undefined private currentContext: common.UIAbilityContext | undefined = undefined
@Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption();
@Monitor('imageKnifeOption',
"imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit")
watchImageKnifeOption() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
}
this.request = undefined
this.componentVersion++
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
aboutToAppear(): void { aboutToAppear(): void {
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} }
@ -95,6 +86,15 @@ export struct ImageKnifeAnimatorComponent {
.onRepeat(this.animatorOption.onRepeat) .onRepeat(this.animatorOption.onRepeat)
} }
watchImageKnifeOption() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
}
this.request = undefined
this.componentVersion++
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true)
}
getCurrentContext(): common.UIAbilityContext { getCurrentContext(): common.UIAbilityContext {
if (this.currentContext == undefined) { if (this.currentContext == undefined) {
this.currentContext = getContext(this) as common.UIAbilityContext this.currentContext = getContext(this) as common.UIAbilityContext
@ -111,7 +111,7 @@ export struct ImageKnifeAnimatorComponent {
height, height,
this.componentVersion, this.componentVersion,
{ {
showPixelMap: async (version: number, pixelMap: PixelMap | string, requestSource: ImageKnifeRequestSource,imageAnimator?: Array<ImageFrameInfo>) => { showPixelMap: (version: number, pixelMap: PixelMap | string,size: Size, requestSource: ImageKnifeRequestSource,imageAnimator?: Array<ImageFrameInfo>) => {
if (version !== this.componentVersion) { if (version !== this.componentVersion) {
return //针对reuse场景不显示历史图片 return //针对reuse场景不显示历史图片
} }

View File

@ -21,13 +21,14 @@ import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData
import { IEngineKey } from '../key/IEngineKey'; import { IEngineKey } from '../key/IEngineKey';
import { DefaultEngineKey } from '../key/DefaultEngineKey'; import { DefaultEngineKey } from '../key/DefaultEngineKey';
@ComponentV2 @Component
export struct ImageKnifeComponent { export struct ImageKnifeComponent {
@Local pixelMap: PixelMap | string | undefined = undefined @Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
@Param syncLoad: boolean = false @State pixelMap: PixelMap | string | ImageContent | undefined = undefined
@Local adaptiveWidth: Length = '100%' @State syncLoad: boolean = false
@Local adaptiveHeight: Length = '100%' @State adaptiveWidth: Length = '100%'
@Local objectFit: ImageFit = ImageFit.Contain @State adaptiveHeight: Length = '100%'
@State objectFit: ImageFit = ImageFit.Contain
private request: ImageKnifeRequest | undefined private request: ImageKnifeRequest | undefined
private lastWidth: number = 0 private lastWidth: number = 0
private lastHeight: number = 0 private lastHeight: number = 0
@ -35,20 +36,6 @@ export struct ImageKnifeComponent {
private currentHeight: number = 0 private currentHeight: number = 0
private componentVersion: number = 0 private componentVersion: number = 0
private currentContext: common.UIAbilityContext | undefined = undefined private currentContext: common.UIAbilityContext | undefined = undefined
@Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption();
@Monitor('imageKnifeOption',
"imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit",'imageKnifeOption.downsampleOf')
watchImageKnifeOption() {
this.clearLastRequest()
this.componentVersion++
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
LogUtil.log("watchImageKnifeOption execute request:width=" + this.currentWidth + " height= " + this.currentHeight
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc)
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
aboutToAppear(): void { aboutToAppear(): void {
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
@ -81,9 +68,9 @@ export struct ImageKnifeComponent {
} }
aboutToRecycle() { aboutToRecycle() {
this.pixelMap = ImageContent.EMPTY
this.clearLastRequest() this.clearLastRequest()
} }
/** /**
* 对已DESTROY的组件不再发起请求 * 对已DESTROY的组件不再发起请求
*/ */
@ -93,7 +80,6 @@ export struct ImageKnifeComponent {
this.request = undefined this.request = undefined
} }
} }
build() { build() {
Image(this.pixelMap) Image(this.pixelMap)
.colorFilter(this.imageKnifeOption.drawingColorFilter) .colorFilter(this.imageKnifeOption.drawingColorFilter)
@ -109,19 +95,29 @@ export struct ImageKnifeComponent {
this.currentHeight = newValue.height as number this.currentHeight = newValue.height as number
this.lastWidth = oldValue.width as number this.lastWidth = oldValue.width as number
this.lastHeight = oldValue.height as number this.lastHeight = oldValue.height as number
if (this.currentWidth <= 0 || this.currentHeight <= 0) {
// 条件1: 宽高值均有效,值>0. 条件2当前宽高与上一次宽高不同 // 存在宽或者高为0,此次重回无意义,无需进行request请求
if (this.currentWidth > 0 && this.currentHeight > 0 && } else {
(this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth)) { // 前提:宽高值均有效,值>0. 条件1当前宽高与上一次宽高不同 条件2:当前是第一次绘制
LogUtil.log("onSizeChange execute request:width=" + this.currentWidth + " height= " + this.currentHeight if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight)
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc) }
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
} }
}) })
} }
watchImageKnifeOption() {
this.clearLastRequest()
this.componentVersion++
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
LogUtil.log("watchImageKnifeOption execute request:width=" + this.currentWidth + " height= " + this.currentHeight
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc)
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
getCurrentContext(): common.UIAbilityContext { getCurrentContext(): common.UIAbilityContext {
if (this.currentContext == undefined) { if (this.currentContext == undefined) {
this.currentContext = getContext(this) as common.UIAbilityContext this.currentContext = getContext(this) as common.UIAbilityContext
@ -138,15 +134,28 @@ export struct ImageKnifeComponent {
height, height,
this.componentVersion, this.componentVersion,
{ {
showPixelMap: async (version: number, pixelMap: PixelMap | string, requestSource: ImageKnifeRequestSource) => { showPixelMap: (version: number, pixelMap: PixelMap | string,size:Size, requestSource: ImageKnifeRequestSource) => {
if (version !== this.componentVersion) { if (version !== this.componentVersion) {
return //针对reuse场景不显示历史图片 return //针对reuse场景不显示历史图片
} }
this.pixelMap = pixelMap this.pixelMap = pixelMap
if (typeof this.pixelMap !== 'string' && this.imageKnifeOption.objectFit === ImageFit.Auto) { //针对静态图高度自适应 if (typeof this.pixelMap !== 'string') {
let info = await this.pixelMap.getImageInfo() if (this.imageKnifeOption.objectFit === ImageFit.Auto) {
this.adaptiveWidth = this.currentWidth
this.adaptiveHeight = info.size.height * this.currentWidth / info.size.width this.adaptiveWidth = this.currentWidth
this.adaptiveHeight = size.height * this.currentWidth / size.width
// if (this.currentWidth / this.currentHeight > info.size.width / info.size.height) {
// this.adaptiveWidth = this.currentWidth
// this.adaptiveHeight = info.size.height * this.currentWidth / this.currentHeight
// }
// else {
// this.adaptiveWidth = info.size.width * this.currentWidth / this.currentHeight
// this.adaptiveHeight = this.currentHeight
// }
}
} else {
//console.info("KKKKKKKKKKK:" + pixelMap)
} }
if (requestSource == ImageKnifeRequestSource.SRC) { if (requestSource == ImageKnifeRequestSource.SRC) {
@ -165,4 +174,8 @@ export struct ImageKnifeComponent {
return this.request return this.request
} }
}
interface KeyCanvas {
keyId: string
} }

View File

@ -1,23 +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
}

View File

@ -1,148 +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 { getScale, highestOneBit, round, SampleSizeRounding } from './DownsampleUtils';
export class FitCenter implements BaseDownsampling {
getName() {
return "FitCenter"
}
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
downsampType: DownsampleStrategy
): number {
//重新计算宽高比;
let outSize: Size = {
width: round(getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) * sourceWidth),
height:round(getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) * sourceHeight)
}
let scaleFactor = downsampType === DownsampleStrategy.FIT_CENTER_QUALITY?
Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height))) :
Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height)))//将整型的缩放因子转换为2的次幂采样大小
if (downsampType === DownsampleStrategy.FIT_CENTER_MEMORY
&& (scaleFactor < (1 / getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)))) {
scaleFactor = scaleFactor << 1;
}
return scaleFactor
}
}
/*宽高进行等比缩放宽高里面最小的比例先放进去
然后再更据原图的缩放比去适配另一边*/
export class AtLeast implements BaseDownsampling {
getName() {
return "AtLeast"
}
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number {
const widthPercentage = requestedWidth / sourceWidth;
const heightPercentage = requestedHeight / sourceHeight;
//返回宽度和高度比例中最大的值
let outSize: Size = {
width: round(Math.max(widthPercentage, heightPercentage) * sourceWidth),
height:round(Math.max(widthPercentage, heightPercentage) * sourceHeight)
}
let scaleFactor = Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height)))
return scaleFactor
}
}
/*请求尺寸大于实际尺寸不进行放大,按照原图展示*/
export class AtMost implements BaseDownsampling {
getName() {
return "AtMost"
}
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)
let outSize: Size = {
width: round((1 / greaterOrEqualSampleSize) * sourceWidth),
height:round((1 / greaterOrEqualSampleSize) * sourceHeight)
}
let scaleFactor = Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height)))
if ((scaleFactor < greaterOrEqualSampleSize)) {
scaleFactor = scaleFactor << 1;
}
return scaleFactor
}
}
/*宽高进行等比缩放宽高里面最大的比例先放进去
然后再更据原图的缩放比去适配另一边*/
export class CenterInside implements BaseDownsampling {
getName() {
return "CenterInside"
}
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
downsampType: DownsampleStrategy
): number {
let outSize: Size = {
width: round(Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)) * sourceWidth),
height:round(Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)) * sourceHeight)
}
//将整型的缩放因子转换为2的次幂采样大小
let scaleFactor = this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight,
downsampType) == SampleSizeRounding.QUALITY ?
Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height))) :
Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height)))
if (this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)
== SampleSizeRounding.MEMORY && (scaleFactor < (1 / Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType))))) {
scaleFactor = scaleFactor << 1;
}
return scaleFactor
}
getSampleSizeType(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
downsampType: DownsampleStrategy
): SampleSizeRounding {
//如果缩放因子为 1表示没有缩放优先选择质量
if (Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)) === 1) {
return SampleSizeRounding.QUALITY
}
//否则,使用 FIL_CENTER 的 SampleSizeRounding 值
return downsampType === DownsampleStrategy.CENTER_OUTSIDE_MEMORY?SampleSizeRounding.MEMORY:SampleSizeRounding.QUALITY
}
}
export enum DownsampleStrategy {
//请求尺寸大于实际尺寸不进行放大
AT_MOST,
//两边自适应内存优先
FIT_CENTER_MEMORY,
//两边自适应质量优先
FIT_CENTER_QUALITY,
//按照宽高比的最大比进行适配内存优先
CENTER_OUTSIDE_MEMORY,
//按照宽高比的最大比进行适配质量优先
CENTER_OUTSIDE_QUALITY,
//宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配
AT_LEAST,
//不进行降采样
NONE,
}

View File

@ -1,58 +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';
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
}
//找出给定整数 i 中最高位的1即最左边的1所代表的值
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 function getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
downsampType: DownsampleStrategy
): number {
if (downsampType === DownsampleStrategy.FIT_CENTER_MEMORY) {
const widthPercentage = requestedWidth / sourceWidth
const heightPercentage = requestedHeight / sourceHeight
return Math.min(widthPercentage, heightPercentage)
} else {
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
return maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor);
}
}
//四舍五入
export function round(value: number): number {
return Math.floor(value + 0.5);
}

View File

@ -1,73 +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,
AtLeast,
DownsampleStrategy,
FitCenter,
} from './DownsampleStartegy';
export class Downsampler {
calculateScaling(
typeValue: string,
sourceWidth: number, //原始宽高
sourceHeight: number, //原始宽高
requestWidth: number, //请求宽高
requestHeight: number, //请求宽高
downsampType: DownsampleStrategy,
): Size {
if (sourceHeight <= 0 || sourceWidth <= 0) {
throw new Error(`Invalid width and height, sourceHeight:${sourceHeight}+ sourceWidth:${sourceWidth}`)
}
let downsampler = this.getDownsampler(downsampType);
let scaleFactor: number =
downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);//缩放比
//基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸
if (typeValue === "png") {
return {
width: Math.floor(sourceWidth / scaleFactor),
height: Math.floor(sourceHeight / scaleFactor)
}
} else if (typeValue === "webp") {
return {
width: Math.round(sourceWidth / scaleFactor),
height: Math.round(sourceHeight / scaleFactor)
}
} else {
return {
width: sourceWidth / scaleFactor,
height: sourceHeight / scaleFactor
}
}
}
getDownsampler(downsampType: DownsampleStrategy) {
switch (downsampType) {
case DownsampleStrategy.FIT_CENTER_MEMORY:
case DownsampleStrategy.FIT_CENTER_QUALITY:
return new FitCenter();
case DownsampleStrategy.AT_MOST:
return new AtMost();
case DownsampleStrategy.CENTER_OUTSIDE_MEMORY:
case DownsampleStrategy.CENTER_OUTSIDE_QUALITY:
return new CenterInside();
case DownsampleStrategy.AT_LEAST:
return new AtLeast();
default:
throw new Error('Unsupported downsampling strategy');
}
}
}

View File

@ -17,7 +17,6 @@ import { ImageKnifeOption } from '../model/ImageKnifeOption';
import { IEngineKey } from './IEngineKey'; import { IEngineKey } from './IEngineKey';
import { PixelMapTransformation } from '../transform/PixelMapTransformation'; import { PixelMapTransformation } from '../transform/PixelMapTransformation';
import { ImageKnifeRequestSource } from '../model/ImageKnifeData'; import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
import { DownsampleStrategy } from '../downsampling/DownsampleStartegy';
@Sendable @Sendable
export class DefaultEngineKey implements IEngineKey { export class DefaultEngineKey implements IEngineKey {
@ -32,9 +31,6 @@ export class DefaultEngineKey implements IEngineKey {
if (imageKnifeOption.transformation) { if (imageKnifeOption.transformation) {
key += "transformation=" + this.getTransformation(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 return key
} }

View File

@ -18,15 +18,55 @@ import { IEngineKey } from '../key/IEngineKey'
import { PixelMapTransformation } from '../transform/PixelMapTransformation' import { PixelMapTransformation } from '../transform/PixelMapTransformation'
import common from '@ohos.app.ability.common'; import common from '@ohos.app.ability.common';
import { Size } from '@kit.ArkUI' import { Size } from '@kit.ArkUI'
import { DownsampleStrategy } from '../downsampling/DownsampleStartegy'
export interface ImageKnifeData { export interface ImageKnifeData {
source: PixelMap | string, source: PixelMap | string, // url
imageWidth: number, imageWidth: number, // 原始宽高大小
imageHeight: number, imageHeight: number,
bufSize?: number, // 图片的字节数
type?:string, type?:string,
imageAnimator?: Array<ImageFrameInfo> imageAnimator?: Array<ImageFrameInfo>
frameCount ?: number // 帧
decodeImages?: Array<DecodeImageInfo> //Image组件或者ImageAnimator组件可以加载一张或者多张
timeInfo?: TimeInfo // 加载图片的各个时间点
errorInfo?: ErrorInfo // 错误
} }
/**
* 解码后的图片的size
*/
export interface DecodeImageInfo {
contentWidth ?: number // 解码后宽高
contentHeight?: number
contentSize ?: number // 大小
}
/**
* 加载的错误信息
*/
export interface ErrorInfo {
phase: string, //图片加载阶段信息,如:网络加载阶段,缓存获取阶段及其解码阶段等
code: number,
httpCode?: number
}
/**
* load检查时间点
*/
export interface TimeInfo {
requestStartTime?: number,
requestEndTime?: number,
requestCancelTime?: number,
memoryCheckStartTime?: number,
memoryCheckEndTime?: number,
diskCheckStartTime?: number,
diskCheckEndTime?: number,
netRequestStartTime?: number,
netRequestEndTime?: number,
decodeStartTime?: number,
decodeEndTime?: number,
}
/** /**
* onComplete成功回调 * onComplete成功回调
*/ */
@ -79,7 +119,8 @@ export interface RequestJobResult {
size?:Size, size?:Size,
type?: string, type?: string,
pixelMapList?:Array<PixelMap>, pixelMapList?:Array<PixelMap>,
delayList?: Array<number> delayList?: Array<number>,
imageKnifeData?: ImageKnifeData,
} }
/** /**
@ -92,7 +133,7 @@ export interface RequestJobRequest {
allHeaders: Map<string, Object>, allHeaders: Map<string, Object>,
componentWidth: number, componentWidth: number,
componentHeight: number, componentHeight: number,
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>, customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>) => Promise<ArrayBuffer | undefined>,
onlyRetrieveFromCache?: boolean onlyRetrieveFromCache?: boolean
requestSource: ImageKnifeRequestSource requestSource: ImageKnifeRequestSource
transformation?: PixelMapTransformation transformation?: PixelMapTransformation
@ -104,9 +145,6 @@ export interface RequestJobRequest {
fileCacheFolder: string, fileCacheFolder: string,
isAnimator?: boolean, isAnimator?: boolean,
moduleName?:string, moduleName?:string,
resName?: string, resName?: string
targetWidth: number
targetHeight: number
downsampType: DownsampleStrategy
} }

View File

@ -17,101 +17,52 @@ import common from '@ohos.app.ability.common'
import { CacheStrategy, ImageKnifeData,EventImage } from './ImageKnifeData'; import { CacheStrategy, ImageKnifeData,EventImage } from './ImageKnifeData';
import { PixelMapTransformation } from '../transform/PixelMapTransformation'; import { PixelMapTransformation } from '../transform/PixelMapTransformation';
import { drawing } from '@kit.ArkGraphics2D'; import { drawing } from '@kit.ArkGraphics2D';
import { DownsampleStrategy } from '../downsampling/DownsampleStartegy'; import { ImageKnifeRequest } from './ImageKnifeRequest';
export interface HeaderOptions { export interface HeaderOptions {
key: string; key: string;
value: Object; value: Object;
} }
interface AnimatorType {
state?: AnimationStatus @Observed
iterations?: number
reverse?: boolean
onStart?:()=>void
onFinish?:()=>void
onPause?:()=>void
onCancel?:()=>void
onRepeat?:()=>void
}
@ObservedV2
export class AnimatorOption { export class AnimatorOption {
@Trace @Track
state?: AnimationStatus = AnimationStatus.Running state?: AnimationStatus = AnimationStatus.Running
@Trace @Track
iterations?: number = -1 iterations?: number = -1
@Trace @Track
reverse?: boolean = false reverse?: boolean = false
@Trace @Track
onStart?:()=>void onStart?:()=>void
@Trace @Track
onFinish?:()=>void onFinish?:()=>void
@Trace @Track
onPause?:()=>void onPause?:()=>void
@Trace @Track
onCancel?:()=>void onCancel?:()=>void
@Trace @Track
onRepeat?:()=>void onRepeat?:()=>void
constructor(option?:AnimatorType) {
this.state = option?.state
this.iterations = option?.iterations
this.reverse = option?.reverse
this.onStart = option?.onStart
this.onFinish = option?.onFinish
this.onPause = option?.onPause
this.onCancel = option?.onCancel
this.onRepeat = option?.onRepeat
}
} }
interface ImageOption {
// 主图资源 @Observed
loadSrc: string | PixelMap | Resource
// 占位图
placeholderSrc?: string | PixelMap | Resource
// 失败占位图
errorholderSrc?: string | PixelMap | Resource
headerOption?: Array<HeaderOptions>;
// 自定义缓存关键字
signature?: string
// 主图填充效果
objectFit?: ImageFit
// 占位图填充效果
placeholderObjectFit?: ImageFit
// 错误图填充效果
errorholderObjectFit?: ImageFit
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>
border?: BorderOptions
// 缓存策略
writeCacheStrategy?: CacheStrategy
// 仅使用缓存加载数据
onlyRetrieveFromCache?: boolean;
priority?: taskpool.Priority
context?: common.UIAbilityContext;
progressListener?: (progress: number) => void;
transformation?: PixelMapTransformation
onLoadListener?: OnLoadCallBack | undefined;
onComplete?:(event:EventImage | undefined) => void
drawingColorFilter?: ColorFilter | drawing.ColorFilter
downsampleOf?: DownsampleStrategy
}
@ObservedV2
export class ImageKnifeOption { export class ImageKnifeOption {
// 主图资源 // 主图资源
@Trace loadSrc: string | PixelMap | Resource = ""; loadSrc: string | PixelMap | Resource = "";
// 占位图 // 占位图
placeholderSrc?: string | PixelMap | Resource; placeholderSrc?: string | PixelMap | Resource;
// 失败占位图 // 失败占位图
errorholderSrc?: string | PixelMap | Resource; errorholderSrc?: string | PixelMap | Resource;
headerOption?: Array<HeaderOptions>; headerOption?: Array<HeaderOptions>;
// 自定义缓存关键字 // 自定义缓存关键字
@Trace signature?: string; signature?: string;
// 主图填充效果 // 主图填充效果
@Trace objectFit?: ImageFit objectFit?: ImageFit
// 占位图填充效果 // 占位图填充效果
placeholderObjectFit?: ImageFit placeholderObjectFit?: ImageFit
// 错误图填充效果 // 错误图填充效果
errorholderObjectFit?: ImageFit errorholderObjectFit?: ImageFit
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined> customGetImage?: (context: Context, src: string | PixelMap | Resource,headers?: Record<string,Object>) => Promise<ArrayBuffer | undefined>
@Trace border?: BorderOptions border?: BorderOptions
// 缓存策略 // 缓存策略
writeCacheStrategy?: CacheStrategy writeCacheStrategy?: CacheStrategy
// 仅使用缓存加载数据 // 仅使用缓存加载数据
@ -119,33 +70,12 @@ export class ImageKnifeOption {
priority?: taskpool.Priority = taskpool.Priority.LOW priority?: taskpool.Priority = taskpool.Priority.LOW
context?: common.UIAbilityContext; context?: common.UIAbilityContext;
progressListener?: (progress: number) => void; progressListener?: (progress: number) => void;
@Trace transformation?: PixelMapTransformation transformation?: PixelMapTransformation
onLoadListener?: OnLoadCallBack | undefined; onLoadListener?: OnLoadCallBack | undefined;
onComplete?:(event:EventImage | undefined) => void onComplete?:(event:EventImage | undefined) => void
drawingColorFilter?: ColorFilter | drawing.ColorFilter drawingColorFilter?: ColorFilter | drawing.ColorFilter
// 下采样 constructor() {
@Trace downsampleOf: DownsampleStrategy = DownsampleStrategy.NONE
constructor(option?:ImageOption) {
this.loadSrc = option?.loadSrc == undefined ? "" : option?.loadSrc
this.placeholderSrc = option?.placeholderSrc
this.errorholderSrc = option?.errorholderSrc
this.headerOption = option?.headerOption
this.signature = option?.signature
this.objectFit = option?.objectFit
this.placeholderObjectFit = option?.placeholderObjectFit
this.errorholderObjectFit = option?.errorholderObjectFit
this.customGetImage = option?.customGetImage
this.border = option?.border
this.writeCacheStrategy = option?.writeCacheStrategy
this.onlyRetrieveFromCache = option?.onlyRetrieveFromCache
this.priority = option?.priority
this.context = option?.context
this.progressListener = option?.progressListener
this.transformation = option?.transformation
this.onLoadListener = option?.onLoadListener
this.onComplete = option?.onComplete
this.drawingColorFilter = option?.drawingColorFilter
this.downsampleOf = option?.downsampleOf==undefined?DownsampleStrategy.NONE:option?.downsampleOf
} }
} }
@ -154,13 +84,13 @@ export class ImageKnifeOption {
*/ */
export interface OnLoadCallBack { export interface OnLoadCallBack {
// 请求开始 // 请求开始
onLoadStart?: () => void; onLoadStart?: (request?: ImageKnifeRequest) => void;
// 请求成功 // 请求成功
onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData) => void; onLoadSuccess?: (data: string | PixelMap | undefined, imageKnifeData: ImageKnifeData, request?: ImageKnifeRequest) => void;
// 请求结束 // 请求结束
onLoadFailed?: (err: string) => void; onLoadFailed?: (err: string, request?: ImageKnifeRequest) => void;
// 请求取消 // 请求取消
onLoadCancel?: (reason: string) => void; onLoadCancel?: (reason: string, request?: ImageKnifeRequest) => void;
} }

View File

@ -14,8 +14,7 @@
*/ */
import { ImageKnifeOption } from './ImageKnifeOption'; import { ImageKnifeOption } from './ImageKnifeOption';
import common from '@ohos.app.ability.common'; import common from '@ohos.app.ability.common';
import { ImageKnifeRequestSource } from './ImageKnifeData'; import { ImageKnifeData, ImageKnifeRequestSource } from './ImageKnifeData';
import { DownsampleStrategy } from '../downsampling/DownsampleStartegy';
export class ImageKnifeRequest { export class ImageKnifeRequest {
@ -28,22 +27,19 @@ export class ImageKnifeRequest {
ImageKnifeRequestCallback: ImageKnifeRequestCallback ImageKnifeRequestCallback: ImageKnifeRequestCallback
componentVersion: number = 0 componentVersion: number = 0
headers: Map<string,Object> = new Map<string,Object>() headers: Map<string,Object> = new Map<string,Object>()
downsampType?: DownsampleStrategy private imageCallBackData: ImageKnifeData | undefined = undefined;
constructor(option: ImageKnifeOption, constructor(option: ImageKnifeOption,
uIAbilityContext: common.UIAbilityContext, uIAbilityContext: common.UIAbilityContext,
width: number, width: number,
height: number, height: number,
version: number, version: number,
ImageKnifeRequestCallback: ImageKnifeRequestCallback, ImageKnifeRequestCallback: ImageKnifeRequestCallback) {
downsampType?: DownsampleStrategy
) {
this.imageKnifeOption = option this.imageKnifeOption = option
this.context = uIAbilityContext this.context = uIAbilityContext
this.componentWidth = width this.componentWidth = width
this.componentHeight = height this.componentHeight = height
this.componentVersion = version this.componentVersion = version
this.ImageKnifeRequestCallback = ImageKnifeRequestCallback this.ImageKnifeRequestCallback = ImageKnifeRequestCallback
this.downsampType = downsampType
} }
// RequestOption调用header对于的方法 // RequestOption调用header对于的方法
addHeader(key: string, value: Object) { addHeader(key: string, value: Object) {
@ -58,6 +54,14 @@ export class ImageKnifeRequest {
} }
}) })
} }
setImageKnifeData(data: ImageKnifeData) {
this.imageCallBackData = data;
}
getImageKnifeData(): ImageKnifeData | undefined {
return this.imageCallBackData
}
} }
export enum ImageKnifeRequestState { export enum ImageKnifeRequestState {
@ -69,5 +73,5 @@ export enum ImageKnifeRequestState {
export interface ImageKnifeRequestCallback { export interface ImageKnifeRequestCallback {
showPixelMap: (version: number, pixelMap: PixelMap | string , requestSource: ImageKnifeRequestSource,imageAnimator?: Array<ImageFrameInfo>) => void; showPixelMap: (version: number, pixelMap: PixelMap | string ,size: Size, requestSource: ImageKnifeRequestSource,imageAnimator?: Array<ImageFrameInfo>) => void;
} }

View File

@ -18,9 +18,9 @@ import Queue from '@ohos.util.Queue';
import { taskpool,Stack } from '@kit.ArkTS'; import { taskpool,Stack } from '@kit.ArkTS';
export class DefaultJobQueue implements IJobQueue { export class DefaultJobQueue implements IJobQueue {
highQueue: Stack<ImageKnifeRequest> = new Stack(); highQueue: Queue<ImageKnifeRequest> = new Queue();
normalQueue: Stack<ImageKnifeRequest> = new Stack(); normalQueue: Queue<ImageKnifeRequest> = new Queue();
lowQueue: Stack<ImageKnifeRequest> = new Stack(); lowQueue: Queue<ImageKnifeRequest> = new Queue();
getQueueLength(): number { getQueueLength(): number {
return this.highQueue.length + this.normalQueue.length + this.lowQueue.length return this.highQueue.length + this.normalQueue.length + this.lowQueue.length
@ -28,11 +28,11 @@ export class DefaultJobQueue implements IJobQueue {
add(request: ImageKnifeRequest): void { add(request: ImageKnifeRequest): void {
if (request.imageKnifeOption.priority === undefined || request.imageKnifeOption.priority === taskpool.Priority.MEDIUM) { if (request.imageKnifeOption.priority === undefined || request.imageKnifeOption.priority === taskpool.Priority.MEDIUM) {
this.normalQueue.push(request) this.normalQueue.add(request)
} else if (request.imageKnifeOption.priority === taskpool.Priority.HIGH) { } else if (request.imageKnifeOption.priority === taskpool.Priority.HIGH) {
this.highQueue.push(request) this.highQueue.add(request)
} else { } else {
this.lowQueue.push(request) this.lowQueue.add(request)
} }
} }

Some files were not shown because too many files have changed in this diff Show More