Compare commits
53 Commits
3.2.0-rc.3
...
master
Author | SHA1 | Date |
---|---|---|
|
bc55de9e2e | |
|
c1426cd35a | |
|
adb78853af | |
|
9e387602f6 | |
|
115118e238 | |
|
acb45a66bc | |
|
25b7899746 | |
|
e41fce46bf | |
|
8601f87865 | |
|
933cc284ec | |
|
fbf4cc88bd | |
|
a21a8f025f | |
|
996fc5c909 | |
|
677ea73337 | |
|
5c22496b96 | |
|
425aa3a5bc | |
|
226d9939be | |
|
2c7473f422 | |
|
17e3787cfa | |
|
915eded1ab | |
|
a1e8e0b15f | |
|
1615da7b7c | |
|
3378d36046 | |
|
f709bd3f01 | |
|
a844860bae | |
|
60ec83850a | |
|
9939c748a8 | |
|
1efe55db1e | |
|
990a9a363f | |
|
618320843f | |
|
db56763a50 | |
|
2f2e562aed | |
|
fc6668cb0d | |
|
ba48f233a7 | |
|
549d9edf48 | |
|
db78e56e9a | |
|
68672e1dc7 | |
|
6719e8ab19 | |
|
7b025a7415 | |
|
912c23f34b | |
|
5f548d1090 | |
|
303ff79be1 | |
|
51e4675957 | |
|
47edcfed3e | |
|
e475dcd30a | |
|
e98984c56a | |
|
fba280904e | |
|
8aebc58a53 | |
|
9ff70d9c78 | |
|
e29c659e89 | |
|
83b42f36b0 | |
|
74bc24d61d | |
|
dac7731794 |
|
@ -0,0 +1,13 @@
|
||||||
|
### 该问题是怎么引起的?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 重现步骤
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 报错信息
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: 缺陷反馈|Bug
|
||||||
|
description: 当您发现了一个缺陷,需要向社区反馈时,请使用此模板。
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels: ["bug"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
感谢对OpenHarmony社区的支持与关注,欢迎反馈缺陷。
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 发生了什么问题?
|
||||||
|
description: 提供尽可能多的信息描述产生了什么问题。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 期望行为是什么?
|
||||||
|
description: 描述期望的行为应该是什么样子的。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 如何复现该缺陷
|
||||||
|
description: 提供尽可能多的信息描述如何复现该缺陷。
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 其他补充信息
|
||||||
|
description: 补充下其他您认为需要提供的信息。
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: 版本或分支信息
|
||||||
|
description: 在哪些版本、分支存在该缺陷的?
|
||||||
|
options:
|
||||||
|
- label: master
|
||||||
|
- label: Release 3.2
|
||||||
|
- label: Release 3.1
|
||||||
|
- label: Release 3.0
|
||||||
|
- label: Release 2.x
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -0,0 +1 @@
|
||||||
|
blank_issues_enabled: false
|
|
@ -0,0 +1,21 @@
|
||||||
|
name: 新需求|Feature
|
||||||
|
description: 您需要反馈或实现一个新需求时,使用此模板。
|
||||||
|
title: "[新需求]: "
|
||||||
|
labels: ["enhancement"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
感谢提出新需求。
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 新需求提供了什么功能?
|
||||||
|
description: 请描述下新需求的功能是什么,解决了什么问题
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 该需求带来的价值、应用场景?
|
||||||
|
description: 请描述下该需求的价值,应用场景等。
|
||||||
|
validations:
|
||||||
|
required: false
|
|
@ -0,0 +1,15 @@
|
||||||
|
name: 问题咨询|Question
|
||||||
|
description: 如果您对OpenHarmony社区有疑问,欢迎反馈咨询。
|
||||||
|
title: "[问题咨询]: "
|
||||||
|
labels: ["question"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
感谢提出问题,我们将安排人答复!
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 问题描述
|
||||||
|
description: 请描述下您的问题
|
||||||
|
validations:
|
||||||
|
required: true
|
|
@ -0,0 +1,72 @@
|
||||||
|
name: 安全问题|Security Issue
|
||||||
|
description: 当您发现安全问题时,使用此模板反馈。
|
||||||
|
title: "[安全问题]: "
|
||||||
|
labels: ["SIG_Security"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
感谢对OpenHarmony社区的支持与关注,欢迎反馈安全问题。
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: 漏洞编号:
|
||||||
|
description: 请描述下漏洞编号。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: 漏洞归属组件
|
||||||
|
description: 请描述下漏洞归属组件。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: 漏洞归属版本
|
||||||
|
description: 请描述下漏洞归属版本。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: CVSS V3.0分值
|
||||||
|
description: 请描述下CVSS V3.0分值。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 漏洞简述
|
||||||
|
description: 请提供下漏洞的描述信息。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 影响性分析说明
|
||||||
|
description: 请描述下该漏洞的影响。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 原理分析
|
||||||
|
description: 请分析下该漏洞的原理。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: 受影响版本
|
||||||
|
description: 请描述下该漏洞的影响版本。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 规避方案或消减措施
|
||||||
|
description: 请描述下该漏洞的规避方案或消减措施。
|
||||||
|
placeholder: ""
|
||||||
|
validations:
|
||||||
|
required: false
|
|
@ -0,0 +1,8 @@
|
||||||
|
### 一、修改说明
|
||||||
|
|
||||||
|
|
||||||
|
### 二、变更内容
|
||||||
|
|
||||||
|
|
||||||
|
### 三、测试建议
|
||||||
|
|
43
CHANGELOG.md
43
CHANGELOG.md
|
@ -1,3 +1,46 @@
|
||||||
|
## 3.2.2-rc.1
|
||||||
|
- Support EXIF metadata carried by images as display orientation
|
||||||
|
|
||||||
|
## 3.2.2-rc.0
|
||||||
|
- Add ImageKnifeComponent to destroy network request interruption
|
||||||
|
- Code refactoring during the download of image resources stage
|
||||||
|
|
||||||
|
## 3.2.1
|
||||||
|
- Release official version
|
||||||
|
|
||||||
|
## 3.2.1-rc.0
|
||||||
|
- Fix bug: CropTransformation is used to crop the original image
|
||||||
|
- Fix bug: After calling the clear all file cache interfaces, the file cache becomes invalid
|
||||||
|
- Optimize the efficiency of file cache initialization.
|
||||||
|
- Add protection at the location where loadSrc is passed in the pixelmap type
|
||||||
|
|
||||||
|
## 3.2.0
|
||||||
|
- When successfully requesting the network, return the httpcode as well
|
||||||
|
- Fix bug: Network error code httpCode returns no data
|
||||||
|
- Modify implementation of ImageFit.Auto: do not modify image height
|
||||||
|
- Modify memory cache limit and file cache limit
|
||||||
|
- Fix record decodeEndTime in imageKinfaData
|
||||||
|
- Add image buffersize in memory cache
|
||||||
|
- Optimize the magic number of heif format image files
|
||||||
|
- Fix bug: The width and height of the downsampling component are inconsistent with the image resolution unit
|
||||||
|
|
||||||
|
## 3.2.0-rc.6
|
||||||
|
- Support LogUtil to turn off log
|
||||||
|
- Support set network request readTimeout and connectTimeout through ImageKnifeOption
|
||||||
|
|
||||||
|
## 3.2.0-rc.5
|
||||||
|
- Enhance: ImageFit.Auto support adaptive height after component width change
|
||||||
|
- Fix bug: call onLoadStart 2 times(import from 3.2.0-rc.0)
|
||||||
|
- Change the initial value of the PixelMap component of ImageKnife to ImageContent EMPTY
|
||||||
|
- Clear memory cache, cancel pixel map release
|
||||||
|
- Loading process log modification
|
||||||
|
- Change the network request readTimeout to 30s
|
||||||
|
|
||||||
|
## 3.2.0-rc.4
|
||||||
|
- Support ICO format images
|
||||||
|
- Fix bug: call reload problem in onLoadFailed
|
||||||
|
- Provide default downsampling strategy to prevent slow loading for large images
|
||||||
|
|
||||||
## 3.2.0-rc.3
|
## 3.2.0-rc.3
|
||||||
- Fix bug: PixelMap size exceeds the maximum value of memory cache and is not cached
|
- Fix bug: PixelMap size exceeds the maximum value of memory cache and is not cached
|
||||||
- Dealing with exception scenarios where imageSource.getImageInfo return undefined
|
- Dealing with exception scenarios where imageSource.getImageInfo return undefined
|
||||||
|
|
3
OAT.xml
3
OAT.xml
|
@ -27,6 +27,7 @@
|
||||||
<filteritem type="filename" name="hvigorw" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
<filteritem type="filename" name="hvigorw" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
||||||
<filteritem type="filename" name="hvigorw.bat" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
<filteritem type="filename" name="hvigorw.bat" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
||||||
<filteritem type="filename" name="hvigor-wrapper.js" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
<filteritem type="filename" name="hvigor-wrapper.js" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
||||||
|
<filteritem type="filename" name=".gitmodules" desc="git配置文件,不添加版权头"/>
|
||||||
<filteritem type="filepath" name="library/src/main/ets/3rd_party/.*" desc="第三方开源软件源码,不修改版权头,以防有修改版权风险"/>
|
<filteritem type="filepath" name="library/src/main/ets/3rd_party/.*" desc="第三方开源软件源码,不修改版权头,以防有修改版权风险"/>
|
||||||
</filefilter>
|
</filefilter>
|
||||||
<filefilter name="defaultPolicyFilter" desc="Filters for compatibility,license header policies">
|
<filefilter name="defaultPolicyFilter" desc="Filters for compatibility,license header policies">
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
<filteritem type="filename" name="hvigorw" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
<filteritem type="filename" name="hvigorw" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
||||||
<filteritem type="filename" name="hvigorw.bat" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
<filteritem type="filename" name="hvigorw.bat" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
||||||
<filteritem type="filename" name="hvigor-wrapper.js" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
<filteritem type="filename" name="hvigor-wrapper.js" desc="hvigorw配置文件,DevEco Studio自动生成,不手动修改"/>
|
||||||
|
<filteritem type="filename" name=".gitmodules" desc="git配置文件,不添加版权头"/>
|
||||||
<filteritem type="filepath" name="library/src/main/ets/3rd_party/.*" desc="第三方开源软件源码,不修改版权头,以防有修改版权风险"/>
|
<filteritem type="filepath" name="library/src/main/ets/3rd_party/.*" desc="第三方开源软件源码,不修改版权头,以防有修改版权风险"/>
|
||||||
</filefilter>
|
</filefilter>
|
||||||
<filefilter name="binaryFileTypePolicyFilter" desc="Filters for binary file policies">
|
<filefilter name="binaryFileTypePolicyFilter" desc="Filters for binary file policies">
|
||||||
|
@ -48,6 +50,7 @@
|
||||||
<filteritem type="filename" name="*.gif" desc="gif图片格式文件,用于展示示例"/>
|
<filteritem type="filename" name="*.gif" desc="gif图片格式文件,用于展示示例"/>
|
||||||
<filteritem type="filename" name="*.jpg" desc="jpg图片格式文件,用于展示示例"/>
|
<filteritem type="filename" name="*.jpg" desc="jpg图片格式文件,用于展示示例"/>
|
||||||
<filteritem type="filename" name="*.jpeg" desc="jpeg图片格式文件,用于展示示例"/>
|
<filteritem type="filename" name="*.jpeg" desc="jpeg图片格式文件,用于展示示例"/>
|
||||||
|
<filteritem type="filename" name="*.heic" desc="heic图片格式文件,用于展示示例"/>
|
||||||
<filteritem type="filename" name="*.json5" desc="hvigor配置文件"/>
|
<filteritem type="filename" name="*.json5" desc="hvigor配置文件"/>
|
||||||
</filefilter>
|
</filefilter>
|
||||||
<filefilter name="defaultFilter" desc="Files not to check">
|
<filefilter name="defaultFilter" desc="Files not to check">
|
||||||
|
|
14
README.md
14
README.md
|
@ -1,3 +1,9 @@
|
||||||
|
## 🚨 **重要提示 | IMPORTANT**
|
||||||
|
>
|
||||||
|
> **⚠️ 此代码仓已归档。新地址请访问 [ImageKnife](https://gitcode.com/openharmony-tpc/ImageKnife)。| ⚠️ This repository has been archived. For the new address, please visit [ImageKnife](https://gitcode.com/openharmony-tpc/ImageKnife).**
|
||||||
|
>
|
||||||
|
---
|
||||||
|
>
|
||||||
# ImageKnife
|
# ImageKnife
|
||||||
|
|
||||||
ImageKnife is a specially crafted image loading and caching library for OpenHarmony, optimized for efficiency, lightness, and simplicity.
|
ImageKnife is a specially crafted image loading and caching library for OpenHarmony, optimized for efficiency, lightness, and simplicity.
|
||||||
|
@ -361,6 +367,14 @@ This project has been verified in the following version:
|
||||||
|
|
||||||
DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)
|
DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)
|
||||||
|
|
||||||
|
## About obfuscation
|
||||||
|
- Code obfuscation, please see[Code Obfuscation](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md)
|
||||||
|
- If you want the imageknife library not to be obfuscated during code obfuscation, you need to add corresponding exclusion rules in the obfuscation rule configuration file obfuscation-rules.txt:
|
||||||
|
```
|
||||||
|
-keep
|
||||||
|
./oh_modules/@ohos/imageknife
|
||||||
|
```
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
If you find any problem during the use, submit an [Issue](https://gitee.com/openharmony-tpc/ImageKnife/issues) or a [PR](https://gitee.com/openharmony-tpc/ImageKnife/issues) to us.
|
If you find any problem during the use, submit an [Issue](https://gitee.com/openharmony-tpc/ImageKnife/issues) or a [PR](https://gitee.com/openharmony-tpc/ImageKnife/issues) to us.
|
||||||
|
|
77
README_zh.md
77
README_zh.md
|
@ -1,3 +1,9 @@
|
||||||
|
## 🚨 **重要提示 | IMPORTANT**
|
||||||
|
>
|
||||||
|
> **⚠️ 此代码仓已归档。新地址请访问 [ImageKnife](https://gitcode.com/openharmony-tpc/ImageKnife)。| ⚠️ This repository has been archived. For the new address, please visit [ImageKnife](https://gitcode.com/openharmony-tpc/ImageKnife).**
|
||||||
|
>
|
||||||
|
---
|
||||||
|
>
|
||||||
# ImageKnife
|
# ImageKnife
|
||||||
|
|
||||||
**专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。**
|
**专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。**
|
||||||
|
@ -355,39 +361,40 @@ async function custom(context: Context, src: string | PixelMap | Resource,header
|
||||||
|
|
||||||
### 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 | customGetImage?:(context: Context, src: string、PixelMap、Resource ,headers?: Record<string, Object>) => Promise<ArrayBuffer、undefined> | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
|
| customGetImage | customGetImage?:(context: Context, src: string、PixelMap、Resource ,headers?: Record<string, Object>) => Promise<ArrayBuffer、undefined> | 自定义下载图片(可选) | | 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) => void | 颜色滤镜效果(可选) |
|
| onComplete | (event:EventImage、undefined) => 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 | 监听图片加载成功与失败 |
|
| 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 | 监听图片加载成功与失败 |
|
||||||
| downsampleOf | DownsampleStrategy | 降采样(可选) |
|
| downsampleOf | DownsampleStrategy | 降采样(可选) |
|
||||||
|
| httpOption | HttpRequestOption | 网络请求配置(可选) |
|
||||||
|
|
||||||
### 降采样类型
|
### 降采样类型
|
||||||
| 类型 | 相关描述 |
|
| 类型 | 相关描述 |
|
||||||
|---------------------|-------------------|
|
|------------------------|-------------------|
|
||||||
| NONE | 不进行降采样 |
|
| NONE | 不进行降采样 |
|
||||||
| AT_MOST | 请求尺寸大于实际尺寸不进行放大 |
|
| AT_MOST | 请求尺寸大于实际尺寸不进行放大 |
|
||||||
| FIT_CENTER_MEMORY | 两边自适应内存优先 |
|
| FIT_CENTER_MEMORY | 两边自适应内存优先 |
|
||||||
| FIT_CENTER_QUALITY | 两边自适应质量优先 |
|
| FIT_CENTER_QUALITY | 两边自适应质量优先 |
|
||||||
| CENTER_OUTSIDE_MEMORY | 宽高缩放比最大的比例,进行缩放适配内存优先 |
|
| CENTER_INSIDE_MEMORY | 宽高缩放比最大的比例,进行缩放适配内存优先 |
|
||||||
| CENTER_OUTSIDE_QUALITY | 宽高缩放比最大的比例,进行缩放适配质量优先 |
|
| CENTER_INSIDE_QUALITY | 宽高缩放比最大的比例,进行缩放适配质量优先 |
|
||||||
| AT_LEAST | 根据宽高的最小的比例,进行适配 |
|
| AT_LEAST | 根据宽高的最小的比例,进行适配 |
|
||||||
|
|
||||||
### ImageKnife接口
|
### ImageKnife接口
|
||||||
|
|
||||||
|
@ -456,6 +463,14 @@ async function custom(context: Context, src: string | PixelMap | Resource,header
|
||||||
在下述版本验证通过:
|
在下述版本验证通过:
|
||||||
DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)
|
DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release(5.0.0.66)
|
||||||
|
|
||||||
|
## 关于混淆
|
||||||
|
- 代码混淆,请查看[代码混淆简介](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md)
|
||||||
|
- 如果希望imageknife库在代码混淆过程中不会被混淆,需要在混淆规则配置文件obfuscation-rules.txt中添加相应的排除规则:
|
||||||
|
|
||||||
|
```
|
||||||
|
-keep
|
||||||
|
./oh_modules/@ohos/imageknife
|
||||||
|
```
|
||||||
## 贡献代码
|
## 贡献代码
|
||||||
|
|
||||||
使用过程中发现任何问题都可以提 [issue](https://gitee.com/openharmony-tpc/ImageKnife/issues)
|
使用过程中发现任何问题都可以提 [issue](https://gitee.com/openharmony-tpc/ImageKnife/issues)
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"signingConfig": "default",
|
"signingConfig": "default",
|
||||||
"compileSdkVersion": 12,
|
"compileSdkVersion": 12,
|
||||||
"compatibleSdkVersion": 12
|
"compatibleSdkVersion": 12,
|
||||||
|
"runtimeOS": "OpenHarmony"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"buildModeSet": [
|
"buildModeSet": [
|
||||||
|
|
|
@ -15,4 +15,7 @@
|
||||||
|
|
||||||
# Keep options:
|
# Keep options:
|
||||||
# -keep-property-name: specifies property names that you want to keep
|
# -keep-property-name: specifies property names that you want to keep
|
||||||
# -keep-global-name: specifies names that you want to keep in the global scope
|
# -keep-global-name: specifies names that you want to keep in the global scope
|
||||||
|
|
||||||
|
-keep
|
||||||
|
./oh_modules/@ohos/imageknife
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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';
|
||||||
|
import { display } from '@kit.ArkUI';
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct AutoImageFit {
|
||||||
|
@State imageWidth: number = 200;
|
||||||
|
private maxWidth: number = px2vp(display.getDefaultDisplaySync().width);
|
||||||
|
|
||||||
|
build() {
|
||||||
|
|
||||||
|
Column() {
|
||||||
|
this.Slider()
|
||||||
|
Column() {
|
||||||
|
Text('Image')
|
||||||
|
Image('https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg')
|
||||||
|
.width('100%')
|
||||||
|
.objectFit(ImageFit.Auto)
|
||||||
|
Text('ImageKnife')
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: 'https://contentcenter-drcn.dbankcdn.cn/pub_1/DevEcoSpace_1_900_9/56/v3/8MdhfSsCSMKj4sA6okUWrg/5uBx56tLTUO3RYQl-E5JiQ.jpg',
|
||||||
|
objectFit: ImageFit.Auto,
|
||||||
|
}
|
||||||
|
}).width('100%')
|
||||||
|
}.width(this.imageWidth).border({ width: 1 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
Slider() {
|
||||||
|
Slider({
|
||||||
|
value: this.imageWidth,
|
||||||
|
min: 100,
|
||||||
|
max: this.maxWidth,
|
||||||
|
style: SliderStyle.OutSet
|
||||||
|
})
|
||||||
|
.blockColor(Color.White)
|
||||||
|
.width('100%')
|
||||||
|
.onChange((value: number) => {
|
||||||
|
this.imageWidth = value;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,8 +38,8 @@ struct DownSamplePage {
|
||||||
|
|
||||||
new SamplingType(2, 'FIT_CENTER_MEMORY'),
|
new SamplingType(2, 'FIT_CENTER_MEMORY'),
|
||||||
new SamplingType(4, 'FIT_CENTER_QUALITY'),
|
new SamplingType(4, 'FIT_CENTER_QUALITY'),
|
||||||
new SamplingType(5, 'CENTER_OUTSIDE_MEMORY'),
|
new SamplingType(5, 'CENTER_INSIDE_MEMORY'),
|
||||||
new SamplingType(6, 'CENTER_OUTSIDE_QUALITY'),
|
new SamplingType(6, 'CENTER_INSIDE_QUALITY'),
|
||||||
new SamplingType(0, 'NONE'),
|
new SamplingType(0, 'NONE'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -86,23 +86,23 @@ struct DownSamplePage {
|
||||||
}
|
}
|
||||||
this.originalPixMap($r('app.media.pngSample'))
|
this.originalPixMap($r('app.media.pngSample'))
|
||||||
this.afterSamplingFunc($r('app.media.pngSample'))
|
this.afterSamplingFunc($r('app.media.pngSample'))
|
||||||
} else if (value === 'CENTER_OUTSIDE_MEMORY') {
|
} else if (value === 'CENTER_INSIDE_MEMORY') {
|
||||||
this.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,
|
||||||
downsampleOf: DownsampleStrategy.CENTER_OUTSIDE_MEMORY
|
downsampleOf: DownsampleStrategy.CENTER_INSIDE_MEMORY
|
||||||
}
|
}
|
||||||
this.originalPixMap($r('app.media.pngSample'))
|
this.originalPixMap($r('app.media.pngSample'))
|
||||||
this.afterSamplingFunc($r('app.media.pngSample'))
|
this.afterSamplingFunc($r('app.media.pngSample'))
|
||||||
} else if (value === 'CENTER_OUTSIDE_QUALITY') {
|
} else if (value === 'CENTER_INSIDE_QUALITY') {
|
||||||
this.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,
|
||||||
downsampleOf: DownsampleStrategy.CENTER_OUTSIDE_QUALITY
|
downsampleOf: DownsampleStrategy.CENTER_INSIDE_QUALITY
|
||||||
}
|
}
|
||||||
this.originalPixMap($r('app.media.pngSample'))
|
this.originalPixMap($r('app.media.pngSample'))
|
||||||
this.afterSamplingFunc($r('app.media.pngSample'))
|
this.afterSamplingFunc($r('app.media.pngSample'))
|
||||||
|
@ -145,8 +145,11 @@ struct DownSamplePage {
|
||||||
|
|
||||||
// 创建pixelMap
|
// 创建pixelMap
|
||||||
imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => {
|
imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => {
|
||||||
|
imageSource.release()
|
||||||
this.afterSampling = pixelMap.getPixelBytesNumber()
|
this.afterSampling = pixelMap.getPixelBytesNumber()
|
||||||
|
pixelMap.release()
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
console.error('Failed to create PixelMap')
|
console.error('Failed to create PixelMap')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -160,8 +163,11 @@ struct DownSamplePage {
|
||||||
}
|
}
|
||||||
// 创建pixelMap
|
// 创建pixelMap
|
||||||
imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => {
|
imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => {
|
||||||
|
imageSource.release()
|
||||||
this.beforeSampling = pixelMap.getPixelBytesNumber()
|
this.beforeSampling = pixelMap.getPixelBytesNumber()
|
||||||
|
pixelMap.release()
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
console.error('Failed to create PixelMap')
|
console.error('Failed to create PixelMap')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -191,8 +197,8 @@ struct DownSamplePage {
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
imageKnifeOption: this.imageKnifeOption
|
imageKnifeOption: this.imageKnifeOption
|
||||||
})
|
})
|
||||||
.height(300)
|
.height(px2vp(300))
|
||||||
.width(300)
|
.width(px2vp(300))
|
||||||
.borderWidth(1)
|
.borderWidth(1)
|
||||||
.borderColor(Color.Pink)
|
.borderColor(Color.Pink)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { ImageKnifeComponent } from '@ohos/libraryimageknife'
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct ErrorMessageDownload {
|
||||||
|
@State httpCode: string = ''
|
||||||
|
@State httpError: string = ''
|
||||||
|
@State storageError: string = ''
|
||||||
|
@State fileError: string = ''
|
||||||
|
@State notPic: string = ''
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
Text(this.httpCode)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:'https://gitee.com/openharmony-tpc/ImageKnife/issues/1111111',
|
||||||
|
errorholderSrc:$r('app.media.failed'),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadFailed:(err)=>{
|
||||||
|
this.httpCode = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).width(100).height(100).margin({bottom:10})
|
||||||
|
|
||||||
|
Text(this.httpError)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:'https://xx.xx.xx',
|
||||||
|
errorholderSrc:$r('app.media.failed'),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadFailed:(err)=>{
|
||||||
|
this.httpError = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).width(100).height(100).margin({bottom:10})
|
||||||
|
|
||||||
|
Text(this.storageError)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:'/data/storage/el2/base/haps/entry/cache/a/b',
|
||||||
|
errorholderSrc:$r('app.media.failed'),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadFailed:(err)=>{
|
||||||
|
this.storageError = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).width(100).height(100).margin({bottom:10})
|
||||||
|
|
||||||
|
Text(this.fileError)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:'file://xx.xx.xx',
|
||||||
|
errorholderSrc:$r('app.media.failed'),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadFailed:(err)=>{
|
||||||
|
this.fileError = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).width(100).height(100).margin({bottom:10})
|
||||||
|
|
||||||
|
Text(this.notPic)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:'xx.xx.xx',
|
||||||
|
errorholderSrc:$r('app.media.failed'),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadFailed:(err)=>{
|
||||||
|
this.notPic = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).width(100).height(100).margin({bottom:10})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,83 +12,91 @@
|
||||||
* 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 } from '@ohos/libraryimageknife'
|
import { AnimatorOption, ImageKnifeAnimatorComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
@Component
|
@Component
|
||||||
struct ImageAnimatorPage {
|
struct ImageAnimatorPage {
|
||||||
@State animatorOption: 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')
|
||||||
},
|
},
|
||||||
onStart:()=>{
|
onStart: () => {
|
||||||
console.log('ImageKnifeAnimatorComponent animatorOption onStart')
|
console.log('ImageKnifeAnimatorComponent animatorOption onStart')
|
||||||
},
|
},
|
||||||
onPause:()=>{
|
onPause: () => {
|
||||||
console.log('ImageKnifeAnimatorComponent animatorOption onPause')
|
console.log('ImageKnifeAnimatorComponent animatorOption onPause')
|
||||||
},
|
},
|
||||||
onCancel:()=>{
|
onCancel: () => {
|
||||||
console.log('ImageKnifeAnimatorComponent animatorOption onCancel')
|
console.log('ImageKnifeAnimatorComponent animatorOption onCancel')
|
||||||
},
|
},
|
||||||
onRepeat:()=>{
|
onRepeat: () => {
|
||||||
console.log('ImageKnifeAnimatorComponent animatorOption onRepeat')
|
console.log('ImageKnifeAnimatorComponent animatorOption onRepeat')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@State animatorOption1: AnimatorOption = {
|
@State animatorOptionFirstFrame: AnimatorOption = {
|
||||||
state: AnimationStatus.Initial
|
state: AnimationStatus.Initial
|
||||||
}
|
}
|
||||||
@State animatorOption2: AnimatorOption = {
|
@State animatorOptionLastFrame: AnimatorOption = {
|
||||||
state: AnimationStatus.Initial,
|
state: AnimationStatus.Initial,
|
||||||
reverse: true
|
reverse: true
|
||||||
}
|
}
|
||||||
|
@State imageKnifeOption: ImageKnifeOption = {
|
||||||
|
loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
||||||
|
placeholderSrc: $r('app.media.loading'),
|
||||||
|
errorholderSrc: $r('app.media.failed')
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
Column(){
|
Column() {
|
||||||
Flex(){
|
Row() {
|
||||||
Button($r('app.string.Play')).onClick(()=>{
|
Button($r('app.string.Play')).onClick(() => {
|
||||||
this.animatorOption.state = AnimationStatus.Running
|
this.animatorOption.state = AnimationStatus.Running
|
||||||
})
|
})
|
||||||
Button($r('app.string.Pause')).onClick(()=>{
|
Button($r('app.string.Pause')).onClick(() => {
|
||||||
this.animatorOption.state = AnimationStatus.Paused
|
this.animatorOption.state = AnimationStatus.Paused
|
||||||
})
|
})
|
||||||
Button($r('app.string.Stop')).onClick(()=>{
|
Button($r('app.string.Stop')).onClick(() => {
|
||||||
this.animatorOption.state = AnimationStatus.Stopped
|
this.animatorOption.state = AnimationStatus.Stopped
|
||||||
})
|
})
|
||||||
Button($r('app.string.Infinite_loop')).onClick(()=>{
|
}
|
||||||
|
|
||||||
|
Row() {
|
||||||
|
Button($r('app.string.Infinite_loop')).onClick(() => {
|
||||||
this.animatorOption.iterations = -1
|
this.animatorOption.iterations = -1
|
||||||
})
|
})
|
||||||
Button($r('app.string.Play_once')).onClick(()=>{
|
Button($r('app.string.Play_once')).onClick(() => {
|
||||||
this.animatorOption.iterations = 1
|
this.animatorOption.iterations = 1
|
||||||
})
|
})
|
||||||
Button($r('app.string.Play_twice')).onClick(()=>{
|
Button($r('app.string.Play_twice')).onClick(() => {
|
||||||
this.animatorOption.iterations = 2
|
this.animatorOption.iterations = 2
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageKnifeAnimatorComponent({
|
ImageKnifeAnimatorComponent({
|
||||||
imageKnifeOption:{
|
imageKnifeOption: this.imageKnifeOption,
|
||||||
loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
animatorOption: this.animatorOption
|
||||||
placeholderSrc:$r('app.media.loading'),
|
}).width(300).height(300).backgroundColor(Color.Orange).margin({ top: 30 })
|
||||||
errorholderSrc:$r('app.media.failed'),
|
|
||||||
border: { radius: 150 }
|
Row({ space: 10 }) {
|
||||||
},animatorOption:this.animatorOption
|
Column() {
|
||||||
}).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: this.imageKnifeOption,
|
||||||
imageKnifeOption:{
|
animatorOption: this.animatorOptionFirstFrame
|
||||||
loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
}).width(120).height(120).backgroundColor(Color.Orange)
|
||||||
placeholderSrc:$r('app.media.loading'),
|
}
|
||||||
errorholderSrc:$r('app.media.failed')
|
|
||||||
},animatorOption:this.animatorOption1
|
Column() {
|
||||||
}).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: this.imageKnifeOption,
|
||||||
imageKnifeOption:{
|
animatorOption: this.animatorOptionLastFrame
|
||||||
loadSrc:'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
}).width(120).height(120).backgroundColor(Color.Orange)
|
||||||
placeholderSrc:$r('app.media.loading'),
|
}
|
||||||
errorholderSrc:$r('app.media.failed')
|
}.margin({ top: 50 }).padding(10)
|
||||||
},animatorOption:this.animatorOption2
|
|
||||||
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
|
|
||||||
}.width('100%').height('100%')
|
}.width('100%').height('100%')
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ import { ImageKnifeRequest,ImageKnife,ImageKnifeComponent } from '@ohos/libraryi
|
||||||
@Entry
|
@Entry
|
||||||
@Component
|
@Component
|
||||||
struct ImageKnifeReload {
|
struct ImageKnifeReload {
|
||||||
|
@State index: number = 0
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
NetWatchState.init()
|
NetWatchState.init()
|
||||||
}
|
}
|
||||||
|
@ -48,6 +49,22 @@ struct ImageKnifeReload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).width(200).height(200).margin({top:10})
|
}).width(200).height(200).margin({top:10})
|
||||||
|
Text("重试5次:" + this.index)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:'https://img-blog.csdn.net/20140514114029140',
|
||||||
|
placeholderSrc:$r('app.media.loading'),
|
||||||
|
errorholderSrc:$r('app.media.failed'),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadFailed:(err,request) => {
|
||||||
|
this.index++
|
||||||
|
if(request != undefined && this.index < 5) {
|
||||||
|
ImageKnife.getInstance().reload(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).width(200).height(200).margin({top:10})
|
||||||
}.width('100%')
|
}.width('100%')
|
||||||
.height('100%')
|
.height('100%')
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,13 +398,13 @@ struct ImageTransformation {
|
||||||
transformations.push(new CropSquareTransformation());
|
transformations.push(new CropSquareTransformation());
|
||||||
}
|
}
|
||||||
if (this.isCropTop) {
|
if (this.isCropTop) {
|
||||||
transformations.push(new CropTransformation(25, 25, 0));
|
transformations.push(new CropTransformation(100, 100, 0));
|
||||||
}
|
}
|
||||||
if (this.isCropCenter) {
|
if (this.isCropCenter) {
|
||||||
transformations.push(new CropTransformation(25, 25, 1));
|
transformations.push(new CropTransformation(100, 100, 1));
|
||||||
}
|
}
|
||||||
if (this.isCropBottom) {
|
if (this.isCropBottom) {
|
||||||
transformations.push(new CropTransformation(25, 25, 2));
|
transformations.push(new CropTransformation(100, 100, 2));
|
||||||
}
|
}
|
||||||
if (this.isSepia) {
|
if (this.isSepia) {
|
||||||
transformations.push(new SepiaTransformation());
|
transformations.push(new SepiaTransformation());
|
||||||
|
|
|
@ -50,6 +50,16 @@ struct Index {
|
||||||
uri: 'pages/SetMaxRequestPage',
|
uri: 'pages/SetMaxRequestPage',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
Button($r('app.string.Single_CallBack')).margin({top:10}).onClick(()=>{
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/SingleImageCallBack',
|
||||||
|
});
|
||||||
|
})
|
||||||
|
Button($r('app.string.Multiple_CallBack')).margin({top:10}).onClick(()=>{
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/MultipleImageCallBack',
|
||||||
|
});
|
||||||
|
})
|
||||||
Button($r('app.string.Test_multiple_images')).margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_multiple_images')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestCommonImage',
|
uri: 'pages/TestCommonImage',
|
||||||
|
@ -72,6 +82,17 @@ struct Index {
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
Button($r('app.string.Test_LocalImageShow')).margin({top:10}).onClick(()=>{
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/LocalImage',
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
||||||
|
Button($r('app.string.Error_Message')).margin({top:10}).onClick(()=>{
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/ErrorMessageDownload',
|
||||||
|
});
|
||||||
|
})
|
||||||
Button($r('app.string.Test_custom_download')).margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_custom_download')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestSetCustomImagePage',
|
uri: 'pages/TestSetCustomImagePage',
|
||||||
|
@ -95,6 +116,12 @@ struct Index {
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
Button($r('app.string.Auto_ImageFit')).margin({top:10}).onClick(()=>{
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/AutoImageFit',
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
||||||
Button($r('app.string.Image_scaling')).margin({top:10}).onClick(()=>{
|
Button($r('app.string.Image_scaling')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TransformPage',
|
uri: 'pages/TransformPage',
|
||||||
|
@ -197,6 +224,11 @@ struct Index {
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
Button($r('app.string.test_exif')).margin({ top: 10 }).onClick(() => {
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/TestImageExif',
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} .width('100%')
|
} .width('100%')
|
||||||
.height('100%')
|
.height('100%')
|
||||||
|
|
|
@ -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 { ImageKnifeComponent } from '@ohos/libraryimageknife';
|
||||||
|
import fs from '@ohos.file.fs';
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct LocalImage {
|
||||||
|
scroller: Scroller = new Scroller;
|
||||||
|
localFile: string = getContext(this).filesDir + '/icon.png'
|
||||||
|
|
||||||
|
aboutToAppear(): void {
|
||||||
|
// 拷贝本地文件
|
||||||
|
let icon: Uint8Array = getContext(this).resourceManager.getMediaContentSync($r('app.media.startIcon'));
|
||||||
|
let file = fs.openSync(this.localFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
|
||||||
|
fs.writeSync(file.fd, icon.buffer);
|
||||||
|
fs.fsyncSync(file.fd);
|
||||||
|
fs.closeSync(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Scroll(this.scroller) {
|
||||||
|
Column() {
|
||||||
|
Text($r('app.string.local_r_file'))
|
||||||
|
.fontSize(30)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $r('app.media.startIcon'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
Text($r('app.string.local_rawfile'))
|
||||||
|
.fontSize(30)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $rawfile('image/startIcon.png'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
Text($r('app.string.Under_context_file'))
|
||||||
|
.fontSize(30)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: this.localFile,
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
Text($r('app.string.local_other_module'))
|
||||||
|
.fontSize(30)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $r('[sharedlibrary].media.startIcon'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
}
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ struct LongImagePage {
|
||||||
//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'),
|
||||||
|
httpOption: {
|
||||||
|
connectTimeout: 60000,
|
||||||
|
readTimeout: 60000
|
||||||
|
},
|
||||||
objectFit: ImageFit.Auto
|
objectFit: ImageFit.Auto
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* 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,ImageKnifeOption } from '@ohos/libraryimageknife';
|
||||||
|
import { CommonDataSource } from './model/CommonDataSource'
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct MultipleImageCallBack {
|
||||||
|
@State hotCommendList: CommonDataSource<string> = new CommonDataSource<string>([])
|
||||||
|
@State componentIndex: number = 0
|
||||||
|
@State startIndex: number = 0
|
||||||
|
@State successIndex: number = 0
|
||||||
|
@State failIndex: number = 0
|
||||||
|
@State cancelJobIndex: number = 0
|
||||||
|
@State cancelLoadIndex: number = 0
|
||||||
|
@State memoryIndex: number = 0
|
||||||
|
@State fileCacheIndex: number = 0
|
||||||
|
@State netIndex: number = 0
|
||||||
|
@State checkText: string = ''
|
||||||
|
private data: Array<string> = []
|
||||||
|
|
||||||
|
aboutToAppear(): void {
|
||||||
|
for (let index = 0; index < 100; index++) {
|
||||||
|
this.data.push(`https://img-blog.csdn.net/20140514114029140?${index}`)
|
||||||
|
}
|
||||||
|
this.hotCommendList.addData(this.hotCommendList.totalCount(), this.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
Row() {
|
||||||
|
Column() {
|
||||||
|
Text('图片总数:' + this.componentIndex)
|
||||||
|
Text('开始回调:' + this.startIndex)
|
||||||
|
Text('成功回调:' + this.successIndex)
|
||||||
|
Text('失败回调:' + this.failIndex)
|
||||||
|
Text('队列取消回调:' + this.cancelJobIndex)
|
||||||
|
Text('加载取消回调:' + this.cancelLoadIndex)
|
||||||
|
Text('内存数量:' + this.memoryIndex)
|
||||||
|
Text('文件数量:' + this.fileCacheIndex)
|
||||||
|
Text('网络数量:' + this.netIndex)
|
||||||
|
}.width('50%')
|
||||||
|
Column() {
|
||||||
|
Button('check')
|
||||||
|
.onClick(()=>{
|
||||||
|
this.checkText = ''
|
||||||
|
if (this.componentIndex !== this.startIndex + this.cancelJobIndex) {
|
||||||
|
this.checkText = this.checkText + '图片总数!=开始+队列取消,'
|
||||||
|
}
|
||||||
|
if(this.startIndex !== this.successIndex + this.failIndex + this.cancelLoadIndex) {
|
||||||
|
this.checkText = this.checkText + '开始回调!=成功+失败+加载取消,'
|
||||||
|
}
|
||||||
|
if(this.successIndex !== this.memoryIndex + this.fileCacheIndex + this.netIndex) {
|
||||||
|
this.checkText = this.checkText + '成功回调!=内存+文件+网络,'
|
||||||
|
}
|
||||||
|
if(this.componentIndex !== this.successIndex + this.failIndex + this.cancelJobIndex + this.cancelLoadIndex) {
|
||||||
|
this.checkText = this.checkText + '图片总数!=成功+失败+加载取消+队列取消,'
|
||||||
|
}
|
||||||
|
if(this.checkText == '') {
|
||||||
|
this.checkText = 'check正确'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Text(this.checkText)
|
||||||
|
}.width('50%')
|
||||||
|
}.width('100%')
|
||||||
|
Column() {
|
||||||
|
WaterFlow() {
|
||||||
|
LazyForEach(this.hotCommendList, (item: string,index: number) => {
|
||||||
|
FlowItem() {
|
||||||
|
Column() {
|
||||||
|
Text(index + '')
|
||||||
|
ImageComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: item,
|
||||||
|
placeholderSrc: $r('app.media.loading'),
|
||||||
|
errorholderSrc: $r('app.media.failed'),
|
||||||
|
onLoadListener: {
|
||||||
|
onLoadStart:()=>{
|
||||||
|
this.startIndex++
|
||||||
|
console.log('image load multiple loadStart:' + this.startIndex)
|
||||||
|
},
|
||||||
|
onLoadSuccess:(pixelmap,imageData,request)=>{
|
||||||
|
this.successIndex++
|
||||||
|
let memory = request?.imageKnifeData?.timeInfo?.memoryCheckEndTime ? 1 : 0
|
||||||
|
let fileCache = request?.imageKnifeData?.timeInfo?.diskCheckEndTime ? 1 : 0
|
||||||
|
let net = request?.imageKnifeData?.timeInfo?.netRequestEndTime ? 1 : 0
|
||||||
|
memory = memory - fileCache
|
||||||
|
fileCache = fileCache - net
|
||||||
|
this.memoryIndex = this.memoryIndex + memory
|
||||||
|
this.fileCacheIndex = this.fileCacheIndex + fileCache
|
||||||
|
this.netIndex = this.netIndex + net
|
||||||
|
console.log('image load multiple loadSuccess:' + this.successIndex)
|
||||||
|
},
|
||||||
|
onLoadFailed:()=>{
|
||||||
|
this.failIndex++
|
||||||
|
console.log('image load multiple loadFail:' + this.failIndex)
|
||||||
|
},
|
||||||
|
onLoadCancel:(message,request)=>{
|
||||||
|
let flag = request?.imageKnifeData?.timeInfo?.netRequestStartTime ? true : false
|
||||||
|
if (flag) {
|
||||||
|
this.cancelLoadIndex++
|
||||||
|
} else {
|
||||||
|
this.cancelJobIndex++
|
||||||
|
}
|
||||||
|
console.log('image load multiple cancelJobIndex:' + this.cancelJobIndex,'cancelLoadIndex' + this.cancelLoadIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},index:this.componentIndex
|
||||||
|
}).width('50%').height(160)
|
||||||
|
}
|
||||||
|
}.height(200)
|
||||||
|
.backgroundColor('#95efd2')
|
||||||
|
}, (item: string) => item)
|
||||||
|
}
|
||||||
|
.cachedCount(0)
|
||||||
|
.columnsTemplate('1fr 1fr')
|
||||||
|
.columnsGap(10)
|
||||||
|
.rowsGap(5)
|
||||||
|
.backgroundColor(0xFAEEE0)
|
||||||
|
.width('100%')
|
||||||
|
}
|
||||||
|
.height('80%')
|
||||||
|
}.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Component
|
||||||
|
struct ImageComponent {
|
||||||
|
@State imageKnifeOption: ImageKnifeOption = new ImageKnifeOption()
|
||||||
|
@Link index: number
|
||||||
|
aboutToAppear(): void {
|
||||||
|
this.index++
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: this.imageKnifeOption
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -130,6 +130,7 @@ struct SingleImage {
|
||||||
editable: true,
|
editable: true,
|
||||||
}
|
}
|
||||||
imageSource.createPixelMap(decodingOptions,(err,pixelMap)=>{
|
imageSource.createPixelMap(decodingOptions,(err,pixelMap)=>{
|
||||||
|
imageSource.release()
|
||||||
this.pixelMap = pixelMap;
|
this.pixelMap = pixelMap;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* 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,ImageKnifeOption } from '@ohos/libraryimageknife';
|
||||||
|
import { CommonDataSource } from './model/CommonDataSource'
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct SingleImageCallBack {
|
||||||
|
@State hotCommendList: CommonDataSource<string> = new CommonDataSource<string>([])
|
||||||
|
@State componentIndex: number = 0
|
||||||
|
@State startIndex: number = 0
|
||||||
|
@State successIndex: number = 0
|
||||||
|
@State failIndex: number = 0
|
||||||
|
@State cancelJobIndex: number = 0
|
||||||
|
@State cancelLoadIndex: number = 0
|
||||||
|
@State memoryIndex: number = 0
|
||||||
|
@State fileCacheIndex: number = 0
|
||||||
|
@State netIndex: number = 0
|
||||||
|
@State checkText: string = ''
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
Row() {
|
||||||
|
Column() {
|
||||||
|
Text('图片总数:' + this.componentIndex)
|
||||||
|
Text('开始回调:' + this.startIndex)
|
||||||
|
Text('成功回调:' + this.successIndex)
|
||||||
|
Text('失败回调:' + this.failIndex)
|
||||||
|
Text('队列取消回调:' + this.cancelJobIndex)
|
||||||
|
Text('加载取消回调:' + this.cancelLoadIndex)
|
||||||
|
Text('内存数量:' + this.memoryIndex)
|
||||||
|
Text('文件数量:' + this.fileCacheIndex)
|
||||||
|
Text('网络数量:' + this.netIndex)
|
||||||
|
}.width('50%')
|
||||||
|
Column() {
|
||||||
|
Button('check')
|
||||||
|
.onClick(()=>{
|
||||||
|
this.checkText = ''
|
||||||
|
if (this.componentIndex !== this.startIndex + this.cancelJobIndex) {
|
||||||
|
this.checkText = this.checkText + '图片总数!=开始+队列取消,'
|
||||||
|
}
|
||||||
|
if(this.startIndex !== this.successIndex + this.failIndex + this.cancelLoadIndex) {
|
||||||
|
this.checkText = this.checkText + '开始回调!=成功+失败+加载取消,'
|
||||||
|
}
|
||||||
|
if(this.successIndex !== this.memoryIndex + this.fileCacheIndex + this.netIndex) {
|
||||||
|
this.checkText = this.checkText + '成功回调!=内存+文件+网络,'
|
||||||
|
}
|
||||||
|
if(this.componentIndex !== this.successIndex + this.failIndex + this.cancelJobIndex + this.cancelLoadIndex) {
|
||||||
|
this.checkText = this.checkText + '图片总数!=成功+失败+加载取消+队列取消,'
|
||||||
|
}
|
||||||
|
if(this.checkText == '') {
|
||||||
|
this.checkText = 'check正确'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Text(this.checkText)
|
||||||
|
}.width('50%')
|
||||||
|
}.width('100%')
|
||||||
|
Column() {
|
||||||
|
ImageComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||||
|
placeholderSrc: $r('app.media.loading'),
|
||||||
|
errorholderSrc: $r('app.media.failed'),
|
||||||
|
onLoadListener: {
|
||||||
|
onLoadStart: () => {
|
||||||
|
this.startIndex++
|
||||||
|
console.log('image load multiple loadStart:' + this.startIndex)
|
||||||
|
},
|
||||||
|
onLoadSuccess: (pixelmap, imageData, request) => {
|
||||||
|
this.successIndex++
|
||||||
|
let memory = request?.imageKnifeData?.timeInfo?.memoryCheckEndTime ? 1 : 0
|
||||||
|
let fileCache = request?.imageKnifeData?.timeInfo?.diskCheckEndTime ? 1 : 0
|
||||||
|
let net = request?.imageKnifeData?.timeInfo?.netRequestEndTime ? 1 : 0
|
||||||
|
memory = memory - fileCache
|
||||||
|
fileCache = fileCache - net
|
||||||
|
this.memoryIndex = this.memoryIndex + memory
|
||||||
|
this.fileCacheIndex = this.fileCacheIndex + fileCache
|
||||||
|
this.netIndex = this.netIndex + net
|
||||||
|
console.log('image load multiple loadSuccess:' + this.successIndex)
|
||||||
|
},
|
||||||
|
onLoadFailed: () => {
|
||||||
|
this.failIndex++
|
||||||
|
console.log('image load multiple loadFail:' + this.failIndex)
|
||||||
|
},
|
||||||
|
onLoadCancel: (message,request) => {
|
||||||
|
let flag = request?.imageKnifeData?.type ? true : false
|
||||||
|
if (flag) {
|
||||||
|
this.cancelLoadIndex++
|
||||||
|
} else {
|
||||||
|
this.cancelJobIndex++
|
||||||
|
}
|
||||||
|
console.log('image load multiple cancelJobIndex:' + this.cancelJobIndex,'cancelLoadIndex' + this.cancelLoadIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},index:this.componentIndex
|
||||||
|
}).width(300).height(300)
|
||||||
|
}
|
||||||
|
.height('80%')
|
||||||
|
}.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Component
|
||||||
|
struct ImageComponent {
|
||||||
|
@State imageKnifeOption: ImageKnifeOption = new ImageKnifeOption()
|
||||||
|
@Link index: number
|
||||||
|
aboutToAppear(): void {
|
||||||
|
this.index++
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: this.imageKnifeOption
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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';
|
||||||
|
import fs from '@ohos.file.fs';
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@Component
|
||||||
|
struct LocalImage {
|
||||||
|
scroller: Scroller = new Scroller;
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Scroll(this.scroller) {
|
||||||
|
Column() {
|
||||||
|
Column() {
|
||||||
|
Text($r('app.string.base_image'))
|
||||||
|
.fontSize(20)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Row() {
|
||||||
|
Image($rawfile('rotate/rotate.jpg')).width(100).height(100).margin({ right: 10 })
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $rawfile('rotate/rotate.jpg'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.margin({ bottom: 20 })
|
||||||
|
|
||||||
|
Column() {
|
||||||
|
Text($r('app.string.rotate_mirror'))
|
||||||
|
.fontSize(20)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Row() {
|
||||||
|
Image($rawfile('rotate/rotate_mirror.jpg')).width(100).height(100).margin({ right: 10 })
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $rawfile('rotate/rotate_mirror.jpg'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
}
|
||||||
|
}.margin({ bottom: 20 })
|
||||||
|
|
||||||
|
Column() {
|
||||||
|
Text($r('app.string.rotate_rotate90'))
|
||||||
|
.fontSize(20)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Row() {
|
||||||
|
Image($rawfile('rotate/rotate_rotate90.jpg')).width(100).height(100).margin({ right: 10 })
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $rawfile('rotate/rotate_rotate90.jpg'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
}
|
||||||
|
}.margin({ bottom: 20 })
|
||||||
|
|
||||||
|
Column() {
|
||||||
|
Text($r('app.string.rotate_mirror_rotate270'))
|
||||||
|
.fontSize(20)
|
||||||
|
.fontWeight(FontWeight.Bold)
|
||||||
|
Row() {
|
||||||
|
Image($rawfile('rotate/rotate_mirror_rotate270.jpg')).width(100).height(100).margin({ right: 10 })
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: $rawfile('rotate/rotate_mirror_rotate270.jpg'),
|
||||||
|
objectFit: ImageFit.Contain
|
||||||
|
}
|
||||||
|
}).width(100).height(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
}
|
||||||
|
.height('100%')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@ struct TestImageKnifeCallbackPage {
|
||||||
@State netEndTime: string | undefined = ''
|
@State netEndTime: string | undefined = ''
|
||||||
@State decodeStartTime: string | undefined = ''
|
@State decodeStartTime: string | undefined = ''
|
||||||
@State decodeEndTime: string | undefined = ''
|
@State decodeEndTime: string | undefined = ''
|
||||||
@State renderTime: string | undefined = ''
|
|
||||||
@State showChild: boolean = true;
|
@State showChild: boolean = true;
|
||||||
|
@State requestFrom: string = '';
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
|
@ -76,7 +76,7 @@ struct TestImageKnifeCallbackPage {
|
||||||
Text($r('app.string.net_end_time', this.netEndTime)).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_start_time', this.decodeStartTime)).fontSize(14)
|
||||||
Text($r('app.string.decode_end_time', this.decodeEndTime)).fontSize(14)
|
Text($r('app.string.decode_end_time', this.decodeEndTime)).fontSize(14)
|
||||||
Text($r('app.string.render_time', this.renderTime)).fontSize(14)
|
Text($r('app.string.request_data_from', this.requestFrom)).fontSize(14)
|
||||||
|
|
||||||
Scroll() {
|
Scroll() {
|
||||||
Column() {
|
Column() {
|
||||||
|
@ -104,11 +104,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -134,11 +129,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Button($r('app.string.local_pic'))
|
Button($r('app.string.local_pic'))
|
||||||
|
@ -163,11 +153,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -195,11 +180,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -225,11 +205,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Button($r('app.string.share_load_failed'))
|
Button($r('app.string.share_load_failed'))
|
||||||
|
@ -254,11 +229,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -286,11 +256,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
border: { radius: 50 },
|
border: { radius: 50 },
|
||||||
onComplete: (event) => {
|
|
||||||
if (event && event.loadingStatus == 0) {
|
|
||||||
this.renderTime = this.formatDate(Date.now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -341,6 +306,7 @@ struct TestImageKnifeCallbackPage {
|
||||||
this.reqStartTime = this.formatDate(data.timeInfo?.requestStartTime);
|
this.reqStartTime = this.formatDate(data.timeInfo?.requestStartTime);
|
||||||
this.memoryStartTime = this.formatDate(data.timeInfo?.memoryCheckStartTime);
|
this.memoryStartTime = this.formatDate(data.timeInfo?.memoryCheckStartTime);
|
||||||
this.memoryEndTime = this.formatDate(data.timeInfo?.memoryCheckEndTime);
|
this.memoryEndTime = this.formatDate(data.timeInfo?.memoryCheckEndTime);
|
||||||
|
this.requestFrom = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +316,7 @@ struct TestImageKnifeCallbackPage {
|
||||||
this.imageHeight = data.imageHeight;
|
this.imageHeight = data.imageHeight;
|
||||||
this.imageSize = data.bufSize;
|
this.imageSize = data.bufSize;
|
||||||
this.frameNum = data.frameCount;
|
this.frameNum = data.frameCount;
|
||||||
|
this.httpCode = data.httpCode
|
||||||
this.decodeSize = JSON.stringify(data.decodeImages);
|
this.decodeSize = JSON.stringify(data.decodeImages);
|
||||||
this.imageType = data.type;
|
this.imageType = data.type;
|
||||||
this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime);
|
this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime);
|
||||||
|
@ -359,6 +326,14 @@ struct TestImageKnifeCallbackPage {
|
||||||
this.netEndTime = this.formatDate(data.timeInfo?.netRequestEndTime);
|
this.netEndTime = this.formatDate(data.timeInfo?.netRequestEndTime);
|
||||||
this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
|
this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
|
||||||
this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
|
this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
|
||||||
|
if (data.timeInfo?.netRequestEndTime !== undefined) {
|
||||||
|
this.requestFrom = 'Http request';
|
||||||
|
} else if (data.timeInfo?.diskCheckEndTime !== undefined) {
|
||||||
|
this.requestFrom = 'File Cache';
|
||||||
|
} else {
|
||||||
|
this.requestFrom = 'Memory Cache';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +342,7 @@ struct TestImageKnifeCallbackPage {
|
||||||
this.errMsg = res;
|
this.errMsg = res;
|
||||||
this.errPhase = data.errorInfo?.phase;
|
this.errPhase = data.errorInfo?.phase;
|
||||||
this.errCode = data.errorInfo?.code;
|
this.errCode = data.errorInfo?.code;
|
||||||
this.httpCode = data.errorInfo?.httpCode;
|
this.httpCode = data.httpCode;
|
||||||
this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime);
|
this.reqEndTime = this.formatDate(data.timeInfo?.requestEndTime);
|
||||||
this.diskStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
|
this.diskStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
|
||||||
this.diskEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
|
this.diskEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
|
||||||
|
@ -376,6 +351,7 @@ struct TestImageKnifeCallbackPage {
|
||||||
this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
|
this.decodeStartTime = this.formatDate(data.timeInfo?.diskCheckStartTime);
|
||||||
this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
|
this.decodeEndTime = this.formatDate(data.timeInfo?.diskCheckEndTime);
|
||||||
this.reqCancelTime = this.formatDate(data.timeInfo?.requestCancelTime)
|
this.reqCancelTime = this.formatDate(data.timeInfo?.requestCancelTime)
|
||||||
|
this.requestFrom = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +382,6 @@ struct TestImageKnifeCallbackPage {
|
||||||
this.netEndTime = ''
|
this.netEndTime = ''
|
||||||
this.decodeStartTime = ''
|
this.decodeStartTime = ''
|
||||||
this.decodeEndTime = ''
|
this.decodeEndTime = ''
|
||||||
this.renderTime = ''
|
|
||||||
this.showChild = true;
|
this.showChild = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,7 +6,11 @@
|
||||||
"mainElement": "EntryAbility",
|
"mainElement": "EntryAbility",
|
||||||
"deviceTypes": [
|
"deviceTypes": [
|
||||||
"default",
|
"default",
|
||||||
"tablet"
|
"tablet",
|
||||||
|
"tv",
|
||||||
|
"wearable",
|
||||||
|
"car",
|
||||||
|
"2in1"
|
||||||
],
|
],
|
||||||
"deliveryWithInstall": true,
|
"deliveryWithInstall": true,
|
||||||
"installationFree": false,
|
"installationFree": false,
|
||||||
|
|
|
@ -40,6 +40,10 @@
|
||||||
"name": "Test_SingleImage",
|
"name": "Test_SingleImage",
|
||||||
"value": "SingleImage"
|
"value": "SingleImage"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_LocalImageShow",
|
||||||
|
"value": "LocalImageShow"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Test_custom_download",
|
"name": "Test_custom_download",
|
||||||
"value": "Global custom download"
|
"value": "Global custom download"
|
||||||
|
@ -106,11 +110,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Display_the_first_frame",
|
"name": "Display_the_first_frame",
|
||||||
"value": "Display the first frame of the animation"
|
"value": "first frame"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Display_the_last_frame",
|
"name": "Display_the_last_frame",
|
||||||
"value": "Display the last frame of the animation"
|
"value": "last frame"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Play",
|
"name": "Play",
|
||||||
|
@ -140,10 +144,26 @@
|
||||||
"name": "Local_SVG",
|
"name": "Local_SVG",
|
||||||
"value": "Local SVG image"
|
"value": "Local SVG image"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "local_r_file",
|
||||||
|
"value": "Local $r file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "local_rawfile",
|
||||||
|
"value": "Local rawfile"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Under_context_file",
|
"name": "Under_context_file",
|
||||||
"value": "Files under context file"
|
"value": "Files under context file"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "local_other_module",
|
||||||
|
"value": "Local other module"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "in_other_module",
|
||||||
|
"value": "in other module"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Network_images",
|
"name": "Network_images",
|
||||||
"value": "Network images"
|
"value": "Network images"
|
||||||
|
@ -562,11 +582,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "img_frame",
|
"name": "img_frame",
|
||||||
"value": "the number of frames of the picture:%d "
|
"value": "the frames of the animator:%d "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "img_content_size",
|
"name": "img_content_size",
|
||||||
"value": "picture decoded width and height size:%s "
|
"value": "decoded width and height size of image:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "err_msg",
|
"name": "err_msg",
|
||||||
|
@ -586,15 +606,15 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "req_start_time",
|
"name": "req_start_time",
|
||||||
"value": "image request start time point:%s "
|
"value": "request start time:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "req_end_time",
|
"name": "req_end_time",
|
||||||
"value": "the point in time at which the image request ends:%s "
|
"value": "request end time:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "req_cancel_time",
|
"name": "req_cancel_time",
|
||||||
"value": "the point at which the image request is cancelled:%s "
|
"value": "request cancel time:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "memory_start_time",
|
"name": "memory_start_time",
|
||||||
|
@ -629,8 +649,8 @@
|
||||||
"value": "decoding end time point:%s "
|
"value": "decoding end time point:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "render_time",
|
"name": "request_data_from",
|
||||||
"value": "render successful time:%s "
|
"value": "request from:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Image_Downsampling_Functionality",
|
"name": "Image_Downsampling_Functionality",
|
||||||
|
@ -647,6 +667,46 @@
|
||||||
{
|
{
|
||||||
"name": "After_the_sampling",
|
"name": "After_the_sampling",
|
||||||
"value": "Size after downsampling"
|
"value": "Size after downsampling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "adjust_size",
|
||||||
|
"value": "Adjust size"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Auto_ImageFit",
|
||||||
|
"value": "ImageFit.Auto:Auto ImageFit Height"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Single_CallBack",
|
||||||
|
"value": "Single image callback"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Multiple_CallBack",
|
||||||
|
"value": "Multiple image callback"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Error_Message",
|
||||||
|
"value": "error message"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "test_exif",
|
||||||
|
"value": "Test display orientation base on the EXIF metadata "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "base_image",
|
||||||
|
"value": "The image don't carry rotation information"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rotate_mirror",
|
||||||
|
"value": "Mirror horizontal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rotate_rotate90",
|
||||||
|
"value": "Rotate 90°"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rotate_mirror_rotate270",
|
||||||
|
"value": "Mirror horizontal and rotate 270°"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -37,6 +37,12 @@
|
||||||
"pages/MaxRequest3",
|
"pages/MaxRequest3",
|
||||||
"pages/TestImageKnifeCallbackPage",
|
"pages/TestImageKnifeCallbackPage",
|
||||||
"pages/TestListImageKnifeCallbackPage",
|
"pages/TestListImageKnifeCallbackPage",
|
||||||
"pages/DownSamplePage"
|
"pages/DownSamplePage",
|
||||||
|
"pages/AutoImageFit",
|
||||||
|
"pages/SingleImageCallBack",
|
||||||
|
"pages/MultipleImageCallBack",
|
||||||
|
"pages/LocalImage",
|
||||||
|
"pages/ErrorMessageDownload",
|
||||||
|
"pages/TestImageExif"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,380 +0,0 @@
|
||||||
{
|
|
||||||
"string": [
|
|
||||||
{
|
|
||||||
"name": "module_desc",
|
|
||||||
"value": "module description"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "EntryAbility_desc",
|
|
||||||
"value": "description"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "EntryAbility_label",
|
|
||||||
"value": "label"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "app_permission_WRITE_IMAGEVIDEO",
|
|
||||||
"value": "获取写入媒体资源权限"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "app_permission_READ_IMAGEVIDEO",
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -40,6 +40,10 @@
|
||||||
"name": "Test_SingleImage",
|
"name": "Test_SingleImage",
|
||||||
"value": "单个图片使用"
|
"value": "单个图片使用"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_LocalImageShow",
|
||||||
|
"value": "本地图片显示"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Test_custom_download",
|
"name": "Test_custom_download",
|
||||||
"value": "全局自定义下载"
|
"value": "全局自定义下载"
|
||||||
|
@ -102,11 +106,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Display_the_first_frame",
|
"name": "Display_the_first_frame",
|
||||||
"value": "动画显示第一帧"
|
"value": "第一帧"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Display_the_last_frame",
|
"name": "Display_the_last_frame",
|
||||||
"value": "动画显示最后一帧"
|
"value": "最后一帧"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Play",
|
"name": "Play",
|
||||||
|
@ -136,9 +140,21 @@
|
||||||
"name": "Local_SVG",
|
"name": "Local_SVG",
|
||||||
"value": "本地资源SVG图片"
|
"value": "本地资源SVG图片"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "local_r_file",
|
||||||
|
"value": "本地$r文件"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "local_rawfile",
|
||||||
|
"value": "本地rawfile文件"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Under_context_file",
|
"name": "Under_context_file",
|
||||||
"value": "本地context files下文件"
|
"value": "本地沙箱路径文件"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "local_other_module",
|
||||||
|
"value": "本地其他模块文件"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Network_images",
|
"name": "Network_images",
|
||||||
|
@ -558,7 +574,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "img_frame",
|
"name": "img_frame",
|
||||||
"value": "图片的帧数:%d "
|
"value": "动图帧数:%d "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "img_content_size",
|
"name": "img_content_size",
|
||||||
|
@ -582,15 +598,15 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "req_start_time",
|
"name": "req_start_time",
|
||||||
"value": "图片的请求开始时间点:%s "
|
"value": "请求开始时间:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "req_end_time",
|
"name": "req_end_time",
|
||||||
"value": "图片请求结束的时间点:%s "
|
"value": "请求结束时间:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "req_cancel_time",
|
"name": "req_cancel_time",
|
||||||
"value": "图片请求取消的时间点:%s "
|
"value": "请求取消时间:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "memory_start_time",
|
"name": "memory_start_time",
|
||||||
|
@ -625,8 +641,8 @@
|
||||||
"value": "解码结束时间点:%s "
|
"value": "解码结束时间点:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "render_time",
|
"name": "request_data_from",
|
||||||
"value": "渲染成功的时间:%s "
|
"value": "请求数据来自于:%s "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Image_Downsampling_Functionality",
|
"name": "Image_Downsampling_Functionality",
|
||||||
|
@ -643,6 +659,46 @@
|
||||||
{
|
{
|
||||||
"name": "After_the_sampling",
|
"name": "After_the_sampling",
|
||||||
"value": "降采样后大小"
|
"value": "降采样后大小"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "adjust_size",
|
||||||
|
"value": "调整大小"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Auto_ImageFit",
|
||||||
|
"value": "ImageFit.Auto:自适用图片高度"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Single_CallBack",
|
||||||
|
"value": "单个图片回调"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Multiple_CallBack",
|
||||||
|
"value": "多张图片回调"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Error_Message",
|
||||||
|
"value": "错误信息"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "base_image",
|
||||||
|
"value": "图片不携带旋转信息"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "test_exif",
|
||||||
|
"value": "测试图片携带的EXIF元数据作为显示方向"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rotate_mirror",
|
||||||
|
"value": "水平翻转"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rotate_rotate90",
|
||||||
|
"value": "顺时针90°"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rotate_mirror_rotate270",
|
||||||
|
"value": "水平翻转后再顺时针270°"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -61,14 +61,14 @@ export default function SamplingTest() {
|
||||||
it('CENTER_OUTSIDE_MEMORY', 3, () => {
|
it('CENTER_OUTSIDE_MEMORY', 3, () => {
|
||||||
let reqSize: Size =
|
let reqSize: Size =
|
||||||
new Downsampler().calculateScaling('jpg', 1024, 1024, 200,
|
new Downsampler().calculateScaling('jpg', 1024, 1024, 200,
|
||||||
200, DownsampleStrategy.CENTER_OUTSIDE_MEMORY)
|
200, DownsampleStrategy.CENTER_INSIDE_MEMORY)
|
||||||
let req = (reqSize.width < 1024 && reqSize.height < 1024)
|
let req = (reqSize.width < 1024 && reqSize.height < 1024)
|
||||||
expect(req).assertEqual(true);
|
expect(req).assertEqual(true);
|
||||||
})
|
})
|
||||||
it('CENTER_OUTSIDE_QUALITY', 4, () => {
|
it('CENTER_OUTSIDE_QUALITY', 4, () => {
|
||||||
let reqSize: Size =
|
let reqSize: Size =
|
||||||
new Downsampler().calculateScaling('jpg', 1024, 1024, 200,
|
new Downsampler().calculateScaling('jpg', 1024, 1024, 200,
|
||||||
200, DownsampleStrategy.CENTER_OUTSIDE_QUALITY)
|
200, DownsampleStrategy.CENTER_INSIDE_QUALITY)
|
||||||
let req = (reqSize.width < 1024 && reqSize.height < 1024)
|
let req = (reqSize.width < 1024 && reqSize.height < 1024)
|
||||||
expect(req).assertEqual(true);
|
expect(req).assertEqual(true);
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
"mainElement": "TestAbility",
|
"mainElement": "TestAbility",
|
||||||
"deviceTypes": [
|
"deviceTypes": [
|
||||||
"default",
|
"default",
|
||||||
"tablet"
|
"tablet",
|
||||||
|
"tv",
|
||||||
|
"wearable",
|
||||||
|
"car",
|
||||||
|
"2in1"
|
||||||
],
|
],
|
||||||
"deliveryWithInstall": true,
|
"deliveryWithInstall": true,
|
||||||
"installationFree": false,
|
"installationFree": false,
|
||||||
|
|
|
@ -18,7 +18,10 @@ export { ImageKnifeAnimatorComponent } from './src/main/ets/components/ImageKnif
|
||||||
|
|
||||||
export { ImageKnife } from './src/main/ets/ImageKnife'
|
export { ImageKnife } from './src/main/ets/ImageKnife'
|
||||||
|
|
||||||
export { ImageKnifeOption , AnimatorOption } from './src/main/ets/model/ImageKnifeOption'
|
export { ImageKnifeOption,
|
||||||
|
AnimatorOption,
|
||||||
|
HttpRequestOption,
|
||||||
|
HeaderOptions } from './src/main/ets/model/ImageKnifeOption'
|
||||||
|
|
||||||
export { ImageKnifeRequest } from './src/main/ets/model/ImageKnifeRequest'
|
export { ImageKnifeRequest } from './src/main/ets/model/ImageKnifeRequest'
|
||||||
|
|
||||||
|
|
|
@ -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.2.0-rc.3",
|
"version": "3.2.2-rc.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ohos/gpu_transform": "^1.0.2"
|
"@ohos/gpu_transform": "^1.0.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { util } from '@kit.ArkTS';
|
||||||
import { image } from '@kit.ImageKit';
|
import { image } from '@kit.ImageKit';
|
||||||
import { common } from '@kit.AbilityKit';
|
import { common } from '@kit.AbilityKit';
|
||||||
import { LogUtil } from './utils/LogUtil';
|
import { LogUtil } from './utils/LogUtil';
|
||||||
|
import { emitter } from '@kit.BasicServicesKit';
|
||||||
|
|
||||||
|
|
||||||
export class ImageKnife {
|
export class ImageKnife {
|
||||||
|
@ -176,6 +177,9 @@ export class ImageKnife {
|
||||||
* @param request 图片请求request
|
* @param request 图片请求request
|
||||||
*/
|
*/
|
||||||
cancel(request:ImageKnifeRequest) {
|
cancel(request:ImageKnifeRequest) {
|
||||||
|
if (typeof request?.imageKnifeOption.loadSrc === 'string' && !request?.drawMainSuccess) {
|
||||||
|
emitter.emit(request.imageKnifeOption.loadSrc + request.componentId)
|
||||||
|
}
|
||||||
request.requestState = ImageKnifeRequestState.DESTROY
|
request.requestState = ImageKnifeRequestState.DESTROY
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -462,12 +466,12 @@ export class ImageKnife {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(request: ImageKnifeRequest,isAnimator?: boolean): Promise<void> {
|
async execute(request: ImageKnifeRequest): Promise<void> {
|
||||||
LogUtil.log('ImageKnife_DataTime_execute.start:'+request.imageKnifeOption.loadSrc)
|
LogUtil.log('ImageKnife_DataTime_execute.start:'+request.imageKnifeOption.loadSrc)
|
||||||
if (this.headerMap.size > 0) {
|
if (this.headerMap.size > 0) {
|
||||||
request.addHeaderMap(this.headerMap)
|
request.addHeaderMap(this.headerMap)
|
||||||
}
|
}
|
||||||
this.dispatcher.enqueue(request,isAnimator)
|
this.dispatcher.enqueue(request)
|
||||||
LogUtil.log('ImageKnife_DataTime_execute.end:'+request.imageKnifeOption.loadSrc)
|
LogUtil.log('ImageKnife_DataTime_execute.end:'+request.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import image from '@ohos.multimedia.image';
|
||||||
import emitter from '@ohos.events.emitter';
|
import emitter from '@ohos.events.emitter';
|
||||||
import { Constants, LoadPhase, LoadPixelMapCode } 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 { IEngineKey } from './key/IEngineKey';
|
import { IEngineKey } from './key/IEngineKey';
|
||||||
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
||||||
import {
|
import {
|
||||||
|
@ -49,10 +48,10 @@ export class ImageKnifeDispatcher {
|
||||||
private engineKey: IEngineKey = new DefaultEngineKey();
|
private engineKey: IEngineKey = new DefaultEngineKey();
|
||||||
|
|
||||||
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('showFromMemomry.start:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion + ' isAnimator=' + isAnimator)
|
||||||
let memoryCache: ImageKnifeData | undefined;
|
let memoryCache: ImageKnifeData | undefined;
|
||||||
let memoryCheckStartTime = Date.now();
|
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,
|
||||||
imageWidth: 0,
|
imageWidth: 0,
|
||||||
|
@ -60,7 +59,7 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memoryCache = ImageKnife.getInstance()
|
memoryCache = ImageKnife.getInstance()
|
||||||
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
|
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator, request.componentWidth, request.componentHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
//记录ImageKnifeRequestSource.SRC 开始内存检查的时间点
|
//记录ImageKnifeRequestSource.SRC 开始内存检查的时间点
|
||||||
|
@ -82,29 +81,26 @@ export class ImageKnifeDispatcher {
|
||||||
// 回调请求开始
|
// 回调请求开始
|
||||||
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
||||||
request.imageKnifeOption.onLoadListener.onLoadStart(request)
|
request.imageKnifeOption.onLoadListener.onLoadStart(request)
|
||||||
LogUtil.log('ImageKnife_DataTime_MemoryCache_onLoadStart:' + request.imageKnifeOption.loadSrc)
|
|
||||||
}
|
}
|
||||||
LogUtil.log('ImageKnife_DataTime_MemoryCache_showPixelMap.start:' + request.imageKnifeOption.loadSrc)
|
|
||||||
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source,
|
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source,
|
||||||
{ width: memoryCache.imageWidth, height: memoryCache.imageHeight }, requestSource, memoryCache.imageAnimator)
|
{ width: memoryCache.imageWidth, height: memoryCache.imageHeight }, requestSource, memoryCache.imageAnimator)
|
||||||
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
|
||||||
|
request.drawMainSuccess = true
|
||||||
// 回调请求开结束
|
// 回调请求开结束
|
||||||
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
||||||
this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData);
|
this.copyMemoryCacheInfo(memoryCache, request.imageKnifeData);
|
||||||
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source, memoryCache, request)
|
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source, memoryCache, request)
|
||||||
LogUtil.log('ImageKnife_DataTime_MemoryCache_onLoadSuccess:' + request.imageKnifeOption.loadSrc)
|
|
||||||
}
|
}
|
||||||
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
||||||
request.requestState = ImageKnifeRequestState.ERROR
|
request.requestState = ImageKnifeRequestState.ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogUtil.log('ImageKnife_DataTime_showFromMemomry.end_hasmemory:' + request.imageKnifeOption.loadSrc)
|
LogUtil.log('showFromMemomry.end_hasmemory:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
LogUtil.log('ImageKnife_DataTime_showFromMemomry.end_nomemory:' + request.imageKnifeOption.loadSrc)
|
LogUtil.log('showFromMemomry.end_nomemory:' + request.componentId + ',srcType:' + requestSource + ',version:' + request.componentVersion)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +112,7 @@ export class ImageKnifeDispatcher {
|
||||||
target.imageWidth = memoryCache.imageWidth;
|
target.imageWidth = memoryCache.imageWidth;
|
||||||
target.imageHeight = memoryCache.imageHeight;
|
target.imageHeight = memoryCache.imageHeight;
|
||||||
target.type = memoryCache.type;
|
target.type = memoryCache.type;
|
||||||
|
target.bufSize = memoryCache.bufSize
|
||||||
target.imageAnimator = memoryCache.imageAnimator;
|
target.imageAnimator = memoryCache.imageAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,11 +151,11 @@ export class ImageKnifeDispatcher {
|
||||||
request.imageKnifeData = callBackData;
|
request.imageKnifeData = callBackData;
|
||||||
}
|
}
|
||||||
|
|
||||||
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
enqueue(request: ImageKnifeRequest,): void {
|
||||||
//初始化加载回调信息
|
//初始化加载回调信息
|
||||||
this.initCallData(request);
|
this.initCallData(request);
|
||||||
//1.内存有的话直接渲染
|
//1.内存有的话直接渲染
|
||||||
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
|
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,request.animator)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 2.内存获取占位图
|
// 2.内存获取占位图
|
||||||
|
@ -172,32 +169,30 @@ export class ImageKnifeDispatcher {
|
||||||
this.jobQueue.add(request)
|
this.jobQueue.add(request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.executeJob(request,isAnimator)
|
this.executeJob(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
executeJob(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
executeJob(request: ImageKnifeRequest): void {
|
||||||
LogUtil.log('ImageKnife_DataTime_executeJob.start:' + request.imageKnifeOption.loadSrc)
|
LogUtil.log('executeJob.start:' + request.componentId + ',version:' + request.componentVersion)
|
||||||
// 加载占位符
|
// 加载占位符
|
||||||
if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) {
|
if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) {
|
||||||
this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)
|
this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)
|
||||||
}
|
}
|
||||||
|
if (request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
||||||
|
request.imageKnifeOption.onLoadListener?.onLoadStart(request)
|
||||||
|
}
|
||||||
// 加载主图
|
// 加载主图
|
||||||
this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)
|
this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,request.animator)
|
||||||
LogUtil.log('ImageKnife_DataTime_executeJob.end:' + request.imageKnifeOption.loadSrc)
|
LogUtil.log('executeJob.end:' + request.componentId + ',version:' + request.componentVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取和显示图片
|
* 获取和显示图片
|
||||||
*/
|
*/
|
||||||
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('getAndShowImage.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
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, currentRequest.componentWidth, currentRequest.componentHeight)
|
||||||
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
|
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
|
||||||
if (requestList == undefined) {
|
if (requestList == undefined) {
|
||||||
requestList = new List()
|
requestList = new List()
|
||||||
|
@ -207,31 +202,19 @@ export class ImageKnifeDispatcher {
|
||||||
requestList.add({ request: currentRequest, source: requestSource })
|
requestList.add({ request: currentRequest, source: requestSource })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
LogUtil.info('image load getAndShowImage start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
let isWatchProgress : boolean = false
|
let isWatchProgress : boolean = false
|
||||||
if (currentRequest.imageKnifeOption.progressListener !== undefined && requestSource === ImageKnifeRequestSource.SRC) {
|
if (currentRequest.imageKnifeOption.progressListener !== undefined && requestSource === ImageKnifeRequestSource.SRC) {
|
||||||
isWatchProgress = true
|
isWatchProgress = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回调请求开始
|
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
|
||||||
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
|
||||||
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart(requestWithSource.request)
|
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadStart:' + currentRequest.imageKnifeOption.loadSrc)
|
|
||||||
}
|
|
||||||
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
|
||||||
isWatchProgress = true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let src: string | number = ''
|
let src: string | number = ''
|
||||||
let moduleName: string = ''
|
let moduleName: string = ''
|
||||||
let resName: string = ''
|
let resName: string = ''
|
||||||
if((imageSrc as Resource).id != undefined) {
|
if((imageSrc as Resource).id != undefined) {
|
||||||
moduleName = (imageSrc as Resource).moduleName
|
moduleName = (imageSrc as Resource).moduleName
|
||||||
src = (imageSrc as Resource).id
|
src = (imageSrc as Resource).id
|
||||||
if(src == -1) {
|
resName = (imageSrc as Resource).params![0]
|
||||||
resName = (imageSrc as Resource).params![0]
|
|
||||||
}
|
|
||||||
} else if(typeof imageSrc == 'string') {
|
} else if(typeof imageSrc == 'string') {
|
||||||
src = imageSrc
|
src = imageSrc
|
||||||
}
|
}
|
||||||
|
@ -256,10 +239,15 @@ export class ImageKnifeDispatcher {
|
||||||
isAnimator:isAnimator,
|
isAnimator:isAnimator,
|
||||||
moduleName: moduleName == '' ? undefined : moduleName,
|
moduleName: moduleName == '' ? undefined : moduleName,
|
||||||
resName: resName == '' ? undefined : resName,
|
resName: resName == '' ? undefined : resName,
|
||||||
caPath: currentRequest.imageKnifeOption.caPath,
|
caPath: currentRequest.imageKnifeOption.httpOption?.caPath,
|
||||||
targetWidth: currentRequest.componentWidth,
|
targetWidth: currentRequest.componentWidth,
|
||||||
targetHeight: currentRequest.componentHeight,
|
targetHeight: currentRequest.componentHeight,
|
||||||
downsampType: currentRequest.imageKnifeOption.downsampleOf == undefined ? DownsampleStrategy.NONE : currentRequest.imageKnifeOption.downsampleOf
|
downsampType: currentRequest.imageKnifeOption.downsampleOf == undefined ? DownsampleStrategy.DEFAULT : currentRequest.imageKnifeOption.downsampleOf,
|
||||||
|
isAutoImageFit: currentRequest.imageKnifeOption.objectFit == ImageFit.Auto,
|
||||||
|
componentId: currentRequest.componentId,
|
||||||
|
componentVersion: currentRequest.componentVersion,
|
||||||
|
connectTimeout: currentRequest.imageKnifeOption.httpOption?.connectTimeout,
|
||||||
|
readTimeout: currentRequest.imageKnifeOption.httpOption?.readTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
if(request.customGetImage == undefined) {
|
if(request.customGetImage == undefined) {
|
||||||
|
@ -272,26 +260,24 @@ export class ImageKnifeDispatcher {
|
||||||
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('getAndShowImage.end:'+ currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
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('etAndShowImage_Task.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
let task = new taskpool.Task(requestJob, request)
|
let task = new taskpool.Task(requestJob, request)
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_Task.end:' + currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_Task.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
if (isWatchProgress){
|
if (isWatchProgress){
|
||||||
emitter.on(Constants.PROGRESS_EMITTER + memoryKey, (data) => {
|
emitter.on(Constants.PROGRESS_EMITTER + memoryKey, (data) => {
|
||||||
this.progressCallBack(requestList! , data?.data?.value as number)
|
this.progressCallBack(requestList! , data?.data?.value as number)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.start(subthread):' + currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_execute.start(subthread):' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
taskpool.execute(task).then((res: Object) => {
|
taskpool.execute(task).then((res: Object) => {
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
emitter.off(Constants.CALLBACK_EMITTER + memoryKey)
|
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)
|
|
||||||
if (isWatchProgress){
|
if (isWatchProgress){
|
||||||
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
|
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
|
||||||
}
|
}
|
||||||
|
@ -314,12 +300,11 @@ export class ImageKnifeDispatcher {
|
||||||
}, requestList!, currentRequest, memoryKey, imageSrc, requestSource, isAnimator)
|
}, requestList!, currentRequest, memoryKey, imageSrc, requestSource, isAnimator)
|
||||||
})
|
})
|
||||||
} else { //主线程请求
|
} else { //主线程请求
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):' + currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_execute.start(mainthread):' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
requestJob(request, requestList).then(() => {
|
requestJob(request, requestList).then(() => {
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
emitter.off(Constants.CALLBACK_EMITTER + memoryKey)
|
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)
|
|
||||||
|
|
||||||
this.doTaskCallback({
|
this.doTaskCallback({
|
||||||
pixelMap: undefined,
|
pixelMap: undefined,
|
||||||
|
@ -357,7 +342,7 @@ export class ImageKnifeDispatcher {
|
||||||
|
|
||||||
private doTaskCallback(requestJobResult: RequestJobResult | undefined, requestList: List<ImageKnifeRequestWithSource> ,
|
private doTaskCallback(requestJobResult: RequestJobResult | undefined, requestList: List<ImageKnifeRequestWithSource> ,
|
||||||
currentRequest: ImageKnifeRequest, memoryKey: string, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean):void {
|
currentRequest: ImageKnifeRequest, memoryKey: string, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean):void {
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.start:'+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_CallBack.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
if (requestJobResult === undefined){
|
if (requestJobResult === undefined){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -368,20 +353,68 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
let pixelmap = requestJobResult.pixelMap;
|
let pixelmap = requestJobResult.pixelMap;
|
||||||
if (pixelmap === undefined) {
|
// 请求取消
|
||||||
LogUtil.error('ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:'+currentRequest.imageKnifeOption.loadSrc + " error: " + requestJobResult.loadFail)
|
if (currentRequest.requestState === ImageKnifeRequestState.DESTROY) {
|
||||||
|
this.executingJobMap.remove(memoryKey);
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
|
if (currentRequest.componentId !== requestWithSource.request.componentId && requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
||||||
|
// 加载占位符
|
||||||
|
if (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
|
||||||
|
requestWithSource.request.imageKnifeOption.placeholderSrc !== undefined &&
|
||||||
|
requestWithSource.request.drawPlayHolderSuccess == false) {
|
||||||
|
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)
|
||||||
|
} else if (requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER &&
|
||||||
|
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
|
||||||
|
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc, ImageKnifeRequestSource.ERROR_HOLDER)
|
||||||
|
} else if (requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
||||||
|
// 加载主图
|
||||||
|
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,requestWithSource.request.animator)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pixelmap !== undefined && typeof pixelmap !== 'string') {
|
||||||
|
(pixelmap as PixelMap).release()
|
||||||
|
}
|
||||||
|
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
||||||
|
// 回调请求成功
|
||||||
|
// 回调请求成功
|
||||||
|
//设置失败回调的时间点
|
||||||
|
let callBackData = requestWithSource.request.imageKnifeData;
|
||||||
|
|
||||||
|
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)
|
||||||
|
LogUtil.log('getAndShowImage cancel:' + requestWithSource.request.componentId + ',srcType:' + requestSource + ',version:' + requestWithSource.request.componentVersion)
|
||||||
|
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel(requestJobResult.loadFail ?? 'component has destroyed from load', requestWithSource.request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.dispatchNextJob()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 请求失败
|
||||||
|
if (pixelmap === undefined) {
|
||||||
|
this.executingJobMap.remove(memoryKey);
|
||||||
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
|
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR
|
||||||
|
LogUtil.error('getAndShowImage_CallBack.pixelmap failed:' + currentRequest.componentId + ',srcType:' +
|
||||||
|
requestSource + ',version:' + currentRequest.componentVersion + " error: " + requestJobResult.loadFail)
|
||||||
// 回调请求失败
|
// 回调请求失败
|
||||||
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) {
|
||||||
this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, requestJobResult.imageKnifeData, requestWithSource.request)
|
this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, requestJobResult.imageKnifeData,
|
||||||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,requestWithSource.request);
|
requestWithSource.request)
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadFailed:'+currentRequest.imageKnifeOption.loadSrc)
|
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail,
|
||||||
|
requestWithSource.request);
|
||||||
}
|
}
|
||||||
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
||||||
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
|
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
|
||||||
|
requestWithSource.request.requestState = ImageKnifeRequestState.PROGRESS
|
||||||
if (this.showFromMemomry(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
|
if (this.showFromMemomry(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
|
||||||
ImageKnifeRequestSource.ERROR_HOLDER) === false) {
|
ImageKnifeRequestSource.ERROR_HOLDER) === false) {
|
||||||
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
|
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
|
||||||
|
@ -389,15 +422,14 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.executingJobMap.remove(memoryKey);
|
|
||||||
this.dispatchNextJob();
|
this.dispatchNextJob();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 保存文件缓存
|
// 保存文件缓存
|
||||||
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) {
|
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) {
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.start:'+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_saveWithoutWriteFile.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize);
|
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize);
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:'+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_saveWithoutWriteFile.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageKnifeData: ImageKnifeData;
|
let imageKnifeData: ImageKnifeData;
|
||||||
|
@ -427,90 +459,76 @@ export class ImageKnifeDispatcher {
|
||||||
//构建缓存保存的ImageKnifeData
|
//构建缓存保存的ImageKnifeData
|
||||||
let saveCacheImageData: ImageKnifeData = {
|
let saveCacheImageData: ImageKnifeData = {
|
||||||
source: pixelmap!,
|
source: pixelmap!,
|
||||||
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
|
imageWidth: requestJobResult.size?.width ?? 0,
|
||||||
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
|
imageHeight: requestJobResult.size?.height ?? 0,
|
||||||
type: requestJobResult.type,
|
type: requestJobResult.type,
|
||||||
|
bufSize: requestJobResult.bufferSize,
|
||||||
imageAnimator: imageKnifeData.imageAnimator
|
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('getAndShowImage_saveMemoryCache.start:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator),
|
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator, currentRequest.componentWidth, currentRequest.componentHeight),
|
||||||
saveCacheImageData);
|
saveCacheImageData);
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:'+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_saveMemoryCache.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
}
|
}
|
||||||
if (requestList !== undefined) {
|
if (requestList !== undefined) {
|
||||||
// key相同的request,一起绘制
|
// key相同的request,一起绘制
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
// 画主图
|
||||||
// 画主图
|
if (requestWithSource.source === ImageKnifeRequestSource.SRC ||
|
||||||
if (requestWithSource.source === ImageKnifeRequestSource.SRC ||
|
requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|
||||||
requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
|
||||||
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
|
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
|
||||||
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
|
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_showPixelMap.start:'+currentRequest.imageKnifeOption.loadSrc)
|
imageKnifeData.source, { width: imageKnifeData.imageWidth, height: imageKnifeData.imageHeight },
|
||||||
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
|
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
|
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
|
||||||
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE;
|
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE;
|
||||||
if (requestWithSource.request.imageKnifeOption.onLoadListener &&
|
requestWithSource.request.drawMainSuccess = true
|
||||||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
|
if (requestWithSource.request.imageKnifeOption.onLoadListener &&
|
||||||
// 回调请求成功
|
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
|
||||||
this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, imageKnifeData,requestWithSource.request);
|
|
||||||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source,
|
|
||||||
saveCacheImageData, requestWithSource.request);
|
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_onLoadSuccess:'+currentRequest.imageKnifeOption.loadSrc)
|
|
||||||
}
|
|
||||||
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
|
|
||||||
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
|
||||||
// 回调请求成功
|
// 回调请求成功
|
||||||
// 回调请求成功
|
this.assembleImageKnifeData(requestWithSource.request.imageKnifeData, imageKnifeData,
|
||||||
//设置失败回调的时间点
|
requestWithSource.request);
|
||||||
let callBackData = requestWithSource.request.imageKnifeData;
|
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(imageKnifeData.source,
|
||||||
|
saveCacheImageData, requestWithSource.request);
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
|
||||||
|
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.executingJobMap.remove(memoryKey);
|
this.executingJobMap.remove(memoryKey);
|
||||||
this.dispatchNextJob();
|
this.dispatchNextJob();
|
||||||
} else {
|
} else {
|
||||||
LogUtil.log('error: no requestlist need to draw for key = ' + memoryKey);
|
LogUtil.log('error: no requestlist need to draw for key = ' + memoryKey);
|
||||||
}
|
}
|
||||||
LogUtil.log('ImageKnife_DataTime_getAndShowImage_CallBack.end:'+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log('getAndShowImage_CallBack.end:' + currentRequest.componentId + ',srcType:' + requestSource + ',version:' + currentRequest.componentVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dispatchNextJob() {
|
dispatchNextJob() {
|
||||||
LogUtil.log('ImageKnife_DataTime_dispatchNextJob.start')
|
LogUtil.log('dispatchNextJob.start')
|
||||||
|
|
||||||
|
// 主图和错误图并发加载时,以及主图加载失败后立即加载错误图,可能会导致短时间内并发数超过maxRequests,故此处减少响应的并发
|
||||||
|
if (this.executingJobMap.length >= this.maxRequests) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
let request = this.jobQueue.pop()
|
let request = this.jobQueue.pop()
|
||||||
if (request === undefined) {
|
if (request === undefined) {
|
||||||
LogUtil.log('ImageKnife_DataTime_dispatchNextJob.end:no any job')
|
LogUtil.log('dispatchNextJob.end:no any job')
|
||||||
break // 队列已无任务
|
break // 队列已无任务
|
||||||
}
|
}
|
||||||
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||||
LogUtil.log('ImageKnife_DataTime_dispatchNextJob.start executeJob:' + request.imageKnifeOption.loadSrc)
|
LogUtil.log('dispatchNextJob.start executeJob:' + request.componentId + ',version:' + request.componentVersion)
|
||||||
this.executeJob(request)
|
this.executeJob(request)
|
||||||
LogUtil.log('ImageKnife_DataTime_dispatchNextJob.end executeJob:' + request.imageKnifeOption.loadSrc)
|
LogUtil.log('dispatchNextJob.end executeJob:' + request.componentId + ',version:' + request.componentVersion)
|
||||||
break
|
break
|
||||||
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
||||||
//构建回调错误信息
|
//构建回调错误信息
|
||||||
|
@ -525,7 +543,8 @@ export class ImageKnifeDispatcher {
|
||||||
};
|
};
|
||||||
callBackData.errorInfo = errorInfo;
|
callBackData.errorInfo = errorInfo;
|
||||||
}
|
}
|
||||||
request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed', request)
|
LogUtil.log('dispatchNextJob cancel:' + request.componentId + ',version:' + request.componentVersion)
|
||||||
|
request.imageKnifeOption.onLoadListener.onLoadCancel('component has destroyed from queue', request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,7 +572,7 @@ export class ImageKnifeDispatcher {
|
||||||
*/
|
*/
|
||||||
@Concurrent
|
@Concurrent
|
||||||
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>) {
|
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>) {
|
||||||
LogUtil.log('ImageKnife_DataTime_requestJob.start:' + request.src + ' requestSource=' + request.requestSource)
|
LogUtil.log('requestJob.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
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)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
CacheStrategy,
|
CacheStrategy,
|
||||||
DecodeImageInfo,
|
DecodeImageInfo,
|
||||||
ErrorInfo,
|
ErrorInfo,
|
||||||
|
FlipRotate,
|
||||||
ImageKnifeData,
|
ImageKnifeData,
|
||||||
ImageKnifeRequestSource,
|
ImageKnifeRequestSource,
|
||||||
ImageKnifeRequestWithSource, RequestJobRequest,
|
ImageKnifeRequestWithSource, RequestJobRequest,
|
||||||
|
@ -35,6 +36,8 @@ import util from '@ohos.util';
|
||||||
import { FileTypeUtil } from './utils/FileTypeUtil';
|
import { FileTypeUtil } from './utils/FileTypeUtil';
|
||||||
import { DownsampleStrategy } from './downsampling/DownsampleStartegy';
|
import { DownsampleStrategy } from './downsampling/DownsampleStartegy';
|
||||||
import { Downsampler } from './downsampling/Downsampler';
|
import { Downsampler } from './downsampling/Downsampler';
|
||||||
|
import { common } from '@kit.AbilityKit';
|
||||||
|
import { ImageLoaderFactory } from './loaderStrategy/ImageLoaderFactory';
|
||||||
|
|
||||||
class RequestData {
|
class RequestData {
|
||||||
receiveSize: number = 2000
|
receiveSize: number = 2000
|
||||||
|
@ -48,13 +51,28 @@ export class ImageKnifeLoader {
|
||||||
static execute(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined, fileKey: string){
|
static execute(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined, fileKey: string){
|
||||||
ImageKnifeLoader.getImageArrayBuffer(request,requestList,fileKey)
|
ImageKnifeLoader.getImageArrayBuffer(request,requestList,fileKey)
|
||||||
}
|
}
|
||||||
|
static getUnit8Array (resBuf: ArrayBuffer) {
|
||||||
|
let unit8 = new Uint8Array(resBuf)
|
||||||
|
let unitString = ''
|
||||||
|
if (unit8.length >= 3) {
|
||||||
|
unitString = unit8[0] + ',' + unit8[1] + ',' + unit8[2]
|
||||||
|
} else if (unit8.length > 0 && unit8.length < 3) {
|
||||||
|
unitString = unit8.length + ''
|
||||||
|
}
|
||||||
|
return unitString
|
||||||
|
}
|
||||||
static async parseImage(resBuf: ArrayBuffer, fileKey: string,
|
static async parseImage(resBuf: ArrayBuffer, fileKey: string,
|
||||||
request: RequestJobRequest, callBackData: ImageKnifeData) {
|
request: RequestJobRequest, callBackData: ImageKnifeData) {
|
||||||
callBackData.bufSize = resBuf.byteLength;
|
callBackData.bufSize = resBuf.byteLength;
|
||||||
let typeValue = new FileTypeUtil().getFileType(resBuf);
|
let typeValue = new FileTypeUtil().getFileType(resBuf);
|
||||||
if(typeValue == null) {
|
if(typeValue == null) {
|
||||||
LogUtil.log('ImageKnife_DataTime_requestJob.end: getFileType is null ' + request.src)
|
LogUtil.log('requestJob.end: getFileType is null: ' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
ImageKnifeLoader.makeEmptyResult(request,'request is not a valid image source', ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT, LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE))
|
ImageKnifeLoader.makeEmptyResult(request,
|
||||||
|
'request is not a valid image source:' + request.src + ',componentId' + request.componentId + ',srcType:' +
|
||||||
|
request.requestSource + ',' +
|
||||||
|
request.componentVersion + ',buffer:' + resBuf.byteLength + ',unit8:' + ImageKnifeLoader.getUnit8Array(resBuf),
|
||||||
|
ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_GET_FORMAT,
|
||||||
|
LoadPixelMapCode.IMAGE_PARSE_FORMAT_FAILED_CODE))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
callBackData.type = typeValue;
|
callBackData.type = typeValue;
|
||||||
|
@ -85,17 +103,13 @@ export class ImageKnifeLoader {
|
||||||
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } })
|
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } })
|
||||||
}
|
}
|
||||||
|
|
||||||
static assembleError(data: ImageKnifeData | undefined, phase: string, code?: number,
|
static assembleError(data: ImageKnifeData | undefined, phase: string, code?: number): ImageKnifeData | undefined {
|
||||||
httpCode?: number): ImageKnifeData | undefined {
|
|
||||||
let errorCallBackData = data?.errorInfo;
|
let errorCallBackData = data?.errorInfo;
|
||||||
if (!errorCallBackData) {
|
if (!errorCallBackData) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
errorCallBackData.phase = phase;
|
errorCallBackData.phase = phase;
|
||||||
errorCallBackData.code = code? code: 0;
|
errorCallBackData.code = code? code: 0;
|
||||||
if (httpCode && httpCode != 0) {
|
|
||||||
errorCallBackData.httpCode = httpCode;
|
|
||||||
}
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +125,7 @@ export class ImageKnifeLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest, callBackData: ImageKnifeData) {
|
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest, callBackData: ImageKnifeData) {
|
||||||
|
LogUtil.log('image parse pixelmap start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
let resPixelmap: PixelMap | undefined = undefined
|
let resPixelmap: PixelMap | undefined = undefined
|
||||||
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
|
let timeInfo: TimeInfo = ImageKnifeLoader.getTimeInfo(callBackData);
|
||||||
|
|
||||||
|
@ -132,6 +147,11 @@ export class ImageKnifeLoader {
|
||||||
let size = imageInfoSync.size
|
let size = imageInfoSync.size
|
||||||
callBackData.imageWidth = size.width;
|
callBackData.imageWidth = size.width;
|
||||||
callBackData.imageHeight = size.height;
|
callBackData.imageHeight = size.height;
|
||||||
|
|
||||||
|
if (request.isAutoImageFit && request.requestSource == ImageKnifeRequestSource.SRC){
|
||||||
|
request.componentHeight = request.componentWidth * size.height / size.width
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((request.downsampType !== DownsampleStrategy.NONE) &&
|
if ((request.downsampType !== DownsampleStrategy.NONE) &&
|
||||||
request.requestSource == ImageKnifeRequestSource.SRC) {
|
request.requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
|
@ -145,6 +165,14 @@ export class ImageKnifeLoader {
|
||||||
}
|
}
|
||||||
timeInfo.decodeStartTime = Date.now();
|
timeInfo.decodeStartTime = Date.now();
|
||||||
|
|
||||||
|
// 获取旋转信息
|
||||||
|
let exif: string | undefined = undefined;
|
||||||
|
await imageSource.getImageProperty(image.PropertyKey.ORIENTATION).then((res)=>{
|
||||||
|
exif = res;
|
||||||
|
}).catch((error: BusinessError)=>{
|
||||||
|
LogUtil.info("The normal image don't have rotation information, " + error.message);
|
||||||
|
})
|
||||||
|
|
||||||
await imageSource.createPixelMap(decodingOptions)
|
await imageSource.createPixelMap(decodingOptions)
|
||||||
.then((pixelmap: PixelMap) => {
|
.then((pixelmap: PixelMap) => {
|
||||||
timeInfo.decodeEndTime = Date.now();
|
timeInfo.decodeEndTime = Date.now();
|
||||||
|
@ -158,15 +186,26 @@ export class ImageKnifeLoader {
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) {
|
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && resPixelmap !== undefined) {
|
||||||
LogUtil.log('ImageKnife_DataTime_requestJob.transform.start:' + request.src)
|
LogUtil.log('requestJob.transform.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
resPixelmap = await request.transformation?.transform(request.context, resPixelmap, request.componentWidth, request.componentHeight);
|
resPixelmap = await request.transformation?.transform(request.context, resPixelmap, request.componentWidth, request.componentHeight);
|
||||||
LogUtil.log('ImageKnife_DataTime_requestJob.transform.end:' + request.src)
|
LogUtil.log('requestJob.transform.end:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
resPixelmap?.setTransferDetached(true)
|
resPixelmap?.setTransferDetached(true)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
LogUtil.error('PixelMap setTransferDetached failed:' + JSON.stringify(e))
|
LogUtil.error('PixelMap setTransferDetached failed:' + JSON.stringify(e))
|
||||||
}
|
}
|
||||||
|
// 设置翻转和旋转角度
|
||||||
|
if(exif && exif !== 'Top-left'){
|
||||||
|
let result = ImageKnifeLoader.getOrientation(exif);
|
||||||
|
if(result.horizontal || result.vertical) {
|
||||||
|
resPixelmap?.flipSync(result.horizontal, result.vertical);
|
||||||
|
}
|
||||||
|
if(result.rotate > 0) {
|
||||||
|
resPixelmap?.rotateSync(result.rotate);
|
||||||
|
}
|
||||||
|
LogUtil.log('The normal image set flip , horizontal=' + result.horizontal + ', vertical=' +result.vertical + ', rotate=' + result.rotate);
|
||||||
|
}
|
||||||
|
|
||||||
//获取各个pixelMap的大小
|
//获取各个pixelMap的大小
|
||||||
if (resPixelmap !== undefined) {
|
if (resPixelmap !== undefined) {
|
||||||
|
@ -189,6 +228,7 @@ export class ImageKnifeLoader {
|
||||||
type:typeValue,
|
type:typeValue,
|
||||||
imageKnifeData:callBackData
|
imageKnifeData:callBackData
|
||||||
}
|
}
|
||||||
|
LogUtil.log('image parse pixelmap end:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
emitter.emit(Constants.CALLBACK_EMITTER + request.memoryKey, { data: { 'value': res } })
|
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,
|
||||||
|
@ -233,6 +273,15 @@ export class ImageKnifeLoader {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
timeInfo.decodeStartTime = Date.now();
|
timeInfo.decodeStartTime = Date.now();
|
||||||
|
|
||||||
|
// 获取旋转信息
|
||||||
|
let exif: string | undefined = undefined;
|
||||||
|
await imageSource.getImageProperty(image.PropertyKey.ORIENTATION).then((res)=>{
|
||||||
|
exif = res;
|
||||||
|
}).catch((error: BusinessError)=>{
|
||||||
|
LogUtil.info("Svg image don't have rotation information, " + error.message);
|
||||||
|
})
|
||||||
|
|
||||||
await imageSource.createPixelMap(opts)
|
await imageSource.createPixelMap(opts)
|
||||||
.then((pixelmap: PixelMap) => {
|
.then((pixelmap: PixelMap) => {
|
||||||
timeInfo.decodeEndTime = Date.now();
|
timeInfo.decodeEndTime = Date.now();
|
||||||
|
@ -240,6 +289,17 @@ export class ImageKnifeLoader {
|
||||||
imageSource.release()
|
imageSource.release()
|
||||||
try {
|
try {
|
||||||
resPixelmap.setTransferDetached(true)
|
resPixelmap.setTransferDetached(true)
|
||||||
|
// 设置翻转和旋转角度
|
||||||
|
if(exif && exif !== 'Top-left'){
|
||||||
|
let result = ImageKnifeLoader.getOrientation(exif);
|
||||||
|
if(result.horizontal || result.vertical) {
|
||||||
|
resPixelmap?.flipSync(result.horizontal, result.vertical);
|
||||||
|
}
|
||||||
|
if(result.rotate > 0) {
|
||||||
|
resPixelmap?.rotateSync(result.rotate);
|
||||||
|
}
|
||||||
|
LogUtil.log('Svg image set flip , horizontal=' + result.horizontal + ', vertical=' +result.vertical + ', rotate=' + result.rotate);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
LogUtil.error('PixelMap setTransferDetached failed:' + JSON.stringify(e))
|
LogUtil.error('PixelMap setTransferDetached failed:' + JSON.stringify(e))
|
||||||
}
|
}
|
||||||
|
@ -295,7 +355,7 @@ export class ImageKnifeLoader {
|
||||||
} else {
|
} else {
|
||||||
timeInfo.decodeStartTime = Date.now()
|
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))
|
||||||
timeInfo.diskCheckEndTime = Date.now()
|
timeInfo.decodeEndTime = Date.now()
|
||||||
let res: RequestJobResult = {
|
let res: RequestJobResult = {
|
||||||
pixelMap: base64str,
|
pixelMap: base64str,
|
||||||
bufferSize: resBuf.byteLength,
|
bufferSize: resBuf.byteLength,
|
||||||
|
@ -395,13 +455,19 @@ export class ImageKnifeLoader {
|
||||||
return headerObj
|
return headerObj
|
||||||
}
|
}
|
||||||
static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string, callBackData: ImageKnifeData){
|
static FileCacheParseImage(request:RequestJobRequest,resBuf:ArrayBuffer,fileKey:string, callBackData: ImageKnifeData){
|
||||||
// 保存文件缓存
|
try {
|
||||||
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
// 保存文件缓存
|
||||||
LogUtil.log('ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:'+request.src)
|
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
LogUtil.log('requestJob_saveFileCacheOnlyFile.start:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
LogUtil.log('ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:'+request.src)
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
||||||
|
LogUtil.log('requestJob_saveFileCacheOnlyFile.end:' + request.componentId + ',srcType:' + request.requestSource + ',' + request.componentVersion)
|
||||||
|
}
|
||||||
|
ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
|
||||||
|
} catch (e) {
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request,
|
||||||
|
'image load FileCacheParseImage error:' + e + ',componentId' + request.componentId + ',srcType:' +
|
||||||
|
request.requestSource + ',' + request.componentVersion)
|
||||||
}
|
}
|
||||||
ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
|
|
||||||
}
|
}
|
||||||
// 获取图片资源
|
// 获取图片资源
|
||||||
static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string) {
|
static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string) {
|
||||||
|
@ -420,181 +486,30 @@ export class ImageKnifeLoader {
|
||||||
errorInfo: error
|
errorInfo: error
|
||||||
};
|
};
|
||||||
|
|
||||||
// 判断自定义下载
|
const loaderStrategy = ImageLoaderFactory.getLoaderStrategy(request);
|
||||||
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == 'string') {
|
if (loaderStrategy) {
|
||||||
// 先从文件缓存获取
|
await loaderStrategy.loadImage(request, requestList, fileKey, callBackData, callBackTimeInfo);
|
||||||
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_CUSTOM_LOAD)
|
} else {
|
||||||
callBackTimeInfo.diskCheckStartTime = Date.now();
|
loadError = `Unsupported request type: ${request.src}`;
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
|
||||||
callBackTimeInfo.diskCheckEndTime = Date.now();
|
|
||||||
if (resBuf === undefined) {
|
|
||||||
LogUtil.log('start customGetImage src=' + request.src)
|
|
||||||
const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request)
|
|
||||||
try {
|
|
||||||
request.customGetImage(request.context, request.src, headerObj)
|
|
||||||
.then((buffer)=>{
|
|
||||||
if(buffer != undefined) {
|
|
||||||
ImageKnifeLoader.FileCacheParseImage(request,buffer,fileKey,callBackData)
|
|
||||||
} else {
|
|
||||||
loadError = 'customGetImage loadFail undefined'
|
|
||||||
ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
|
|
||||||
}
|
|
||||||
}).catch((err:string)=>{
|
|
||||||
ImageKnifeLoader.makeEmptyResult(request,err, ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE))
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
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 {
|
|
||||||
if (typeof request.src === 'string') {
|
|
||||||
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)
|
|
||||||
callBackTimeInfo.diskCheckEndTime = Date.now()
|
|
||||||
if (resBuf !== undefined){
|
|
||||||
LogUtil.log('success get image from filecache for key = ' + fileKey + ' src = ' + request.src)
|
|
||||||
}
|
|
||||||
else if (request.onlyRetrieveFromCache != true) {
|
|
||||||
LogUtil.log('HttpDownloadClient.start:' + request.src)
|
|
||||||
callBackTimeInfo.netRequestStartTime = Date.now();
|
|
||||||
let httpRequest = http.createHttp();
|
|
||||||
let progress: number = 0
|
|
||||||
let arrayBuffers:ArrayBuffer[] = []
|
|
||||||
const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request)
|
|
||||||
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
|
|
||||||
arrayBuffers.push(data)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (request.isWatchProgress) {
|
|
||||||
httpRequest.on('dataReceiveProgress', (data: RequestData) => {
|
|
||||||
// 下载进度
|
|
||||||
if (data != undefined && (typeof data.receiveSize == 'number') && (typeof data.totalSize == 'number')) {
|
|
||||||
let percent = Math.round(((data.receiveSize * 1.0) / (data.totalSize * 1.0)) * 100)
|
|
||||||
if (progress !== percent) {
|
|
||||||
progress = percent
|
|
||||||
if (requestList === undefined) {
|
|
||||||
// 子线程
|
|
||||||
emitter.emit(Constants.PROGRESS_EMITTER + request.memoryKey, { data: { 'value': progress } })
|
|
||||||
}else {
|
|
||||||
// 主线程请求
|
|
||||||
requestList!.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
|
||||||
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
|
||||||
requestWithSource.request.imageKnifeOption.progressListener(progress)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
let promise = httpRequest.requestInStream(request.src, {
|
|
||||||
header: headerObj,
|
|
||||||
method: http.RequestMethod.GET,
|
|
||||||
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
|
||||||
connectTimeout: 60000,
|
|
||||||
readTimeout: 0,
|
|
||||||
// usingProtocol:http.HttpProtocol.HTTP1_1
|
|
||||||
// header: new Header('application/json')
|
|
||||||
caPath: request.caPath === undefined ? undefined : request.caPath,
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.then((data: number) => {
|
|
||||||
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, undefined, data)
|
|
||||||
callBackTimeInfo.netRequestEndTime = Date.now();
|
|
||||||
if (data == 200 || data == 206 || data == 204) {
|
|
||||||
resBuf = combineArrayBuffers(arrayBuffers)
|
|
||||||
ImageKnifeLoader.FileCacheParseImage(request,resBuf,fileKey, callBackData)
|
|
||||||
} else {
|
|
||||||
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) => {
|
|
||||||
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)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callBackTimeInfo.netRequestEndTime = Date.now();
|
|
||||||
loadError = 'onlyRetrieveFromCache,do not fetch image src = ' + request.src
|
|
||||||
}
|
|
||||||
} 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.stat(file.fd).then(async (stat) =>{
|
|
||||||
let buf = new ArrayBuffer(stat.size);
|
|
||||||
await fs.read(file.fd, buf).then((readLen) => {
|
|
||||||
resBuf = buf;
|
|
||||||
fs.closeSync(file.fd);
|
|
||||||
}).catch((err:BusinessError) => {
|
|
||||||
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) => {
|
|
||||||
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) => {
|
|
||||||
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 { //从本地文件获取
|
|
||||||
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE)
|
|
||||||
try {
|
|
||||||
let stat = fs.statSync(request.src);
|
|
||||||
if (stat.size > 0) {
|
|
||||||
let file = fs.openSync(request.src, fs.OpenMode.READ_ONLY);
|
|
||||||
resBuf = new ArrayBuffer(stat.size);
|
|
||||||
fs.readSync(file.fd, resBuf);
|
|
||||||
fs.closeSync(file);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_LOCAL_FILE, LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE)
|
|
||||||
loadError = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (typeof request.src == 'number') { //从资源文件获取
|
|
||||||
let manager = request.context.createModuleContext(request.moduleName).resourceManager
|
|
||||||
if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) {
|
|
||||||
if(request.src == -1) {
|
|
||||||
let resName = request.resName as string
|
|
||||||
resBuf = (await manager.getMediaByName(resName.substring(resName.lastIndexOf(".") + 1))).buffer as ArrayBuffer
|
|
||||||
} else {
|
|
||||||
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
|
||||||
}
|
|
||||||
} else if (resBuf == undefined && request.requestSource != ImageKnifeRequestSource.SRC) {
|
|
||||||
if(request.src == -1) {
|
|
||||||
let resName = request.resName as string
|
|
||||||
resBuf = (await manager.getMediaByName(resName.substring(resName.lastIndexOf(".") + 1))).buffer as ArrayBuffer
|
|
||||||
} else {
|
|
||||||
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resBuf === undefined){
|
|
||||||
callBackTimeInfo.requestEndTime = Date.now();
|
callBackTimeInfo.requestEndTime = Date.now();
|
||||||
ImageKnifeLoader.makeEmptyResult(request,loadError ,callBackData)
|
ImageKnifeLoader.makeEmptyResult(request, loadError, callBackData);
|
||||||
return
|
|
||||||
}
|
}
|
||||||
ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData)
|
|
||||||
}
|
}
|
||||||
|
static isLocalLoadSrc(context: Object | undefined, loadSrc: string): boolean {
|
||||||
|
if (context != undefined) {
|
||||||
|
let fileDir: string = (context as common.UIAbilityContext).filesDir as string;
|
||||||
|
let cacheDir: string = (context as common.UIAbilityContext).cacheDir as string
|
||||||
|
if (loadSrc.startsWith(fileDir) || loadSrc.startsWith(cacheDir)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
static getDownsamplerDecodingOptions(typeValue: string, request: RequestJobRequest, size: Size,
|
static getDownsamplerDecodingOptions(typeValue: string, request: RequestJobRequest, size: Size,
|
||||||
SRC?: ImageKnifeRequestSource):image.DecodingOptions {
|
SRC?: ImageKnifeRequestSource):image.DecodingOptions {
|
||||||
let reqSize =
|
let reqSize =
|
||||||
new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth, request.targetHeight,
|
new Downsampler().calculateScaling(typeValue, size.width, size.height,
|
||||||
request.downsampType)
|
vp2px(request.targetWidth), vp2px(request.targetHeight), request.downsampType)
|
||||||
if (typeValue == 'svg') {
|
if (typeValue == 'svg') {
|
||||||
return {
|
return {
|
||||||
editable: true,
|
editable: true,
|
||||||
|
@ -614,4 +529,39 @@ export class ImageKnifeLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getOrientation(orientation: string | undefined){
|
||||||
|
let horizontal: boolean = false;
|
||||||
|
let vertical: boolean = false;
|
||||||
|
let rotate: number= 0;
|
||||||
|
switch (orientation){
|
||||||
|
case 'Top-left': break
|
||||||
|
case 'Top-right':
|
||||||
|
horizontal = true;
|
||||||
|
break;
|
||||||
|
case 'Bottom-left':
|
||||||
|
vertical = true;
|
||||||
|
break
|
||||||
|
case 'Bottom-right':
|
||||||
|
rotate = 180;
|
||||||
|
break;
|
||||||
|
case 'Left-top':
|
||||||
|
horizontal = true;
|
||||||
|
rotate = 270;
|
||||||
|
break
|
||||||
|
case 'Right-top':
|
||||||
|
rotate = 90;
|
||||||
|
break;
|
||||||
|
case 'Left-bottom':
|
||||||
|
rotate = 270;
|
||||||
|
break
|
||||||
|
case 'Right-bottom':
|
||||||
|
horizontal = true;
|
||||||
|
rotate = 90;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data: FlipRotate = { horizontal: horizontal, vertical: vertical, rotate:rotate };
|
||||||
|
return data
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,6 @@ import util from '@ohos.util';
|
||||||
import { FileUtils } from '../utils/FileUtils';
|
import { FileUtils } from '../utils/FileUtils';
|
||||||
import fs from '@ohos.file.fs';
|
import fs from '@ohos.file.fs';
|
||||||
import { LogUtil } from '../utils/LogUtil';
|
import { LogUtil } from '../utils/LogUtil';
|
||||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
|
||||||
|
|
||||||
const INT_MAX = 2147483647
|
const INT_MAX = 2147483647
|
||||||
/**
|
/**
|
||||||
|
@ -33,24 +32,21 @@ export class FileCache {
|
||||||
private lruCache: util.LRUCache<string, number>
|
private lruCache: util.LRUCache<string, number>
|
||||||
private isInited: boolean = false
|
private isInited: boolean = false
|
||||||
private context?: Context
|
private context?: Context
|
||||||
readonly defaultMaxSize: number = 512;
|
readonly defaultMaxMemorySize: number = 10 * 1024 * 1024 * 1024;
|
||||||
readonly defaultSize: number = INT_MAX;
|
readonly defaultMemorySize: number = 1024 * 1024 * 1024;
|
||||||
readonly defaultMaxMemorySize: number = 512 * 1024 * 1024;
|
|
||||||
readonly defaultMemorySize: number = 128 * 1024 * 1024;
|
|
||||||
|
|
||||||
constructor(context: Context, size: number, memory: number) {
|
constructor(context: Context, size: number, memory: number) {
|
||||||
if (size <= 0 || size > INT_MAX) {
|
if (size <= 0 || size > INT_MAX) {
|
||||||
size = this.defaultSize
|
size = INT_MAX;
|
||||||
}
|
}
|
||||||
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
|
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
|
||||||
memory = this.defaultMemorySize
|
memory = this.defaultMemorySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lruCache = new util.LRUCache(size);
|
this.lruCache = new util.LRUCache(size);
|
||||||
this.maxMemory = memory
|
this.maxMemory = memory;
|
||||||
this.currentMemory = 0;
|
this.currentMemory = 0;
|
||||||
this.maxSize = size
|
this.maxSize = size;
|
||||||
this.context = context
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,6 +56,7 @@ export class FileCache {
|
||||||
if (this.isInited) {
|
if (this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let startTime = Date.now()
|
||||||
if (this.context && path.startsWith(this.context.cacheDir) === true) {
|
if (this.context && path.startsWith(this.context.cacheDir) === true) {
|
||||||
this.path = path
|
this.path = path
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,6 +70,7 @@ export class FileCache {
|
||||||
interface CacheFileInfo {
|
interface CacheFileInfo {
|
||||||
file: string;
|
file: string;
|
||||||
ctime: number;
|
ctime: number;
|
||||||
|
size: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按照上次访问该文件的时间排序
|
// 按照上次访问该文件的时间排序
|
||||||
|
@ -81,29 +79,29 @@ export class FileCache {
|
||||||
let stat: fs.Stat | undefined = await FileUtils.getInstance().Stat(this.path + filenames[i])
|
let stat: fs.Stat | undefined = await FileUtils.getInstance().Stat(this.path + filenames[i])
|
||||||
cachefiles.push({
|
cachefiles.push({
|
||||||
file: filenames[i],
|
file: filenames[i],
|
||||||
ctime: stat === undefined ? 0 : stat.ctime
|
ctime: stat === undefined ? 0 : stat.ctime,
|
||||||
|
size: stat?.size ?? 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let sortedCachefiles: CacheFileInfo[] = cachefiles.sort((a, b) => a.ctime - b.ctime)
|
let sortedCachefiles: CacheFileInfo[] = cachefiles.sort((a, b) => a.ctime - b.ctime)
|
||||||
|
|
||||||
for (let i = 0; i < sortedCachefiles.length; i++) {
|
for (let i = 0; i < sortedCachefiles.length; i++) {
|
||||||
let buf: ArrayBuffer | undefined = await FileUtils.getInstance().readFile(this.path + sortedCachefiles[i].file)
|
const fileSize: number = sortedCachefiles[i].size;
|
||||||
if (buf !== undefined) {
|
// 处理数量超过size的场景,移除即将排除的文件
|
||||||
// 处理数量超过size的场景,移除即将排除的文件
|
if (this.lruCache.length == this.maxSize && !this.lruCache.contains(sortedCachefiles[i].file)) {
|
||||||
if (this.lruCache.length == this.maxSize && !this.lruCache.contains(sortedCachefiles[i].file)) {
|
let remove: number | undefined = this.lruCache.remove(this.lruCache.keys()[0])
|
||||||
let remove: number | undefined = this.lruCache.remove(this.lruCache.keys()[0])
|
if (remove !== undefined) {
|
||||||
if (remove !== undefined) {
|
FileUtils.getInstance().deleteFile(this.path + this.lruCache.keys()[0])
|
||||||
FileUtils.getInstance().deleteFile(this.path + this.lruCache.keys()[0])
|
this.removeMemorySize(fileSize)
|
||||||
this.removeMemorySize(buf)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lruCache.put(sortedCachefiles[i].file, buf.byteLength)
|
|
||||||
this.addMemorySize(buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.lruCache.put(sortedCachefiles[i].file, fileSize)
|
||||||
|
this.addMemorySize(fileSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.trimToSize();
|
this.trimToSize();
|
||||||
|
LogUtil.info('image init initFileCache:' + (Date.now() - startTime) + ',num:' + filenames.length + ',nums:' + this.lruCache.length + ',size:' + this.currentMemory)
|
||||||
this.isInited = true
|
this.isInited = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +192,6 @@ export class FileCache {
|
||||||
if (!this.isInited) {
|
if (!this.isInited) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.isInited = false
|
|
||||||
this.lruCache.clear()
|
this.lruCache.clear()
|
||||||
this.currentMemory = 0;
|
this.currentMemory = 0;
|
||||||
|
|
||||||
|
@ -202,8 +199,6 @@ export class FileCache {
|
||||||
for (let i = 0; i < filenames.length; i++) {
|
for (let i = 0; i < filenames.length; i++) {
|
||||||
await FileUtils.getInstance().deleteFile(this.path + filenames[i])
|
await FileUtils.getInstance().deleteFile(this.path + filenames[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isInited = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size(): number {
|
size(): number {
|
||||||
|
|
|
@ -21,23 +21,23 @@ export class MemoryLruCache implements IMemoryCache {
|
||||||
currentMemory: number = 0
|
currentMemory: number = 0
|
||||||
maxSize: number = 0
|
maxSize: number = 0
|
||||||
private lruCache: util.LRUCache<string, ImageKnifeData>
|
private lruCache: util.LRUCache<string, ImageKnifeData>
|
||||||
readonly defaultMaxSize: number = 4096
|
readonly defaultMaxSize: number = 65536;
|
||||||
readonly defaultSize: number = 512
|
readonly defaultSize: number = 512;
|
||||||
readonly defaultMaxMemorySize: number = 1024 * 1024 * 1024
|
readonly defaultMaxMemorySize: number = 10 * 1024 * 1024 * 1024;
|
||||||
readonly defaultMemorySize: number = 128 * 1024 * 1024
|
readonly defaultMemorySize: number = 1024 * 1024 * 1024;
|
||||||
|
|
||||||
constructor(size: number, memory: number) {
|
constructor(size: number, memory: number) {
|
||||||
if (size <= 0 || size > this.defaultMaxSize) {
|
if (size <= 0 || size > this.defaultMaxSize) {
|
||||||
size = this.defaultSize
|
size = this.defaultSize;
|
||||||
}
|
}
|
||||||
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
|
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
|
||||||
memory = this.defaultMemorySize
|
memory = this.defaultMemorySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lruCache = new util.LRUCache(size);
|
this.lruCache = new util.LRUCache(size);
|
||||||
this.maxMemory = memory
|
this.maxMemory = memory;
|
||||||
this.maxSize = size
|
this.maxSize = size;
|
||||||
this.currentMemory = 0
|
this.currentMemory = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加缓存键值对
|
// 添加缓存键值对
|
||||||
|
@ -115,9 +115,8 @@ export class MemoryLruCache implements IMemoryCache {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.currentMemory -= value.source.getPixelBytesNumber();
|
this.currentMemory -= value.source.getPixelBytesNumber();
|
||||||
value.source.release()
|
// value.source.release()
|
||||||
}
|
}
|
||||||
// LogUtil.info('MemoryCache removeMemorySize: ' + value.source.getPixelBytesNumber() + ' currentMemory:' + this.currentMemory)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import common from '@ohos.app.ability.common';
|
||||||
import { ImageKnife } from '../ImageKnife';
|
import { ImageKnife } from '../ImageKnife';
|
||||||
import { LogUtil } from '../utils/LogUtil';
|
import { LogUtil } from '../utils/LogUtil';
|
||||||
import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
|
import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
|
||||||
|
import { emitter } from '@kit.BasicServicesKit';
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export struct ImageKnifeAnimatorComponent {
|
export struct ImageKnifeAnimatorComponent {
|
||||||
|
@ -26,11 +27,13 @@ export struct ImageKnifeAnimatorComponent {
|
||||||
@State pixelMap: PixelMap | string | undefined = undefined
|
@State pixelMap: PixelMap | string | undefined = undefined
|
||||||
@State imageAnimator: Array<ImageFrameInfo> | undefined = undefined
|
@State imageAnimator: Array<ImageFrameInfo> | undefined = undefined
|
||||||
@State adaptiveWidth: Length = '100%'
|
@State adaptiveWidth: Length = '100%'
|
||||||
@State adaptiveHeight: Length = '100%'
|
@State adaptiveHeight: Length | undefined = '100%'
|
||||||
@State objectFit: ImageFit = ImageFit.Contain
|
@State objectFit: ImageFit = ImageFit.Contain
|
||||||
|
private componentId: number = 0
|
||||||
private request: ImageKnifeRequest | undefined
|
private request: ImageKnifeRequest | undefined
|
||||||
private lastWidth: number = 0
|
private lastWidth: number = 0
|
||||||
private lastHeight: number = 0
|
private lastHeight: number = 0
|
||||||
|
private isImageFitAutoResize: boolean = false
|
||||||
private currentWidth: number = 0
|
private currentWidth: number = 0
|
||||||
private currentHeight: number = 0
|
private currentHeight: number = 0
|
||||||
private componentVersion: number = 0
|
private componentVersion: number = 0
|
||||||
|
@ -38,23 +41,33 @@ export struct ImageKnifeAnimatorComponent {
|
||||||
|
|
||||||
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
|
||||||
|
this.componentId = this.getUniqueId()
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToDisappear(): void {
|
aboutToDisappear(): void {
|
||||||
if (this.request !== undefined) {
|
this.emitterDestroy()
|
||||||
this.request.requestState = ImageKnifeRequestState.DESTROY
|
this.clearLastRequest()
|
||||||
this.request = undefined
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToRecycle() {
|
aboutToRecycle() {
|
||||||
|
this.emitterDestroy()
|
||||||
|
this.clearLastRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
emitterDestroy() {
|
||||||
|
if (typeof this.request?.imageKnifeOption.loadSrc === 'string' && !this.request?.drawMainSuccess) {
|
||||||
|
emitter.emit(this.request.imageKnifeOption.loadSrc + this.componentId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 对已DESTROY的组件不再发起请求
|
||||||
|
*/
|
||||||
|
private clearLastRequest(){
|
||||||
if (this.request !== undefined) {
|
if (this.request !== undefined) {
|
||||||
this.request.requestState = ImageKnifeRequestState.DESTROY
|
this.request.requestState = ImageKnifeRequestState.DESTROY
|
||||||
this.request = undefined
|
this.request = undefined
|
||||||
}
|
}
|
||||||
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
ImageAnimator()
|
ImageAnimator()
|
||||||
.images(this.imageAnimator)
|
.images(this.imageAnimator)
|
||||||
|
@ -75,8 +88,18 @@ export struct ImageKnifeAnimatorComponent {
|
||||||
} else {
|
} else {
|
||||||
// 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制
|
// 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制
|
||||||
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
|
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
|
||||||
LogUtil.log('execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight)
|
LogUtil.log('onSizeChange execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
|
||||||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true)
|
' loadSrc = ' + this.imageKnifeOption.loadSrc +
|
||||||
|
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
|
||||||
|
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
|
||||||
|
' componentId = ' + this.componentId)
|
||||||
|
|
||||||
|
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize) {
|
||||||
|
this.isImageFitAutoResize = false
|
||||||
|
} else {
|
||||||
|
ImageKnife.getInstance().execute(this.getRequest(
|
||||||
|
this.currentWidth, this.currentHeight, this.componentId))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -88,12 +111,17 @@ export struct ImageKnifeAnimatorComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
watchImageKnifeOption() {
|
watchImageKnifeOption() {
|
||||||
if (this.request !== undefined) {
|
this.clearLastRequest()
|
||||||
this.request.requestState = ImageKnifeRequestState.DESTROY
|
|
||||||
}
|
|
||||||
this.request = undefined
|
|
||||||
this.componentVersion++
|
this.componentVersion++
|
||||||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true)
|
this.isImageFitAutoResize = false
|
||||||
|
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||||||
|
LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
|
||||||
|
' loadSrc = ' + this.imageKnifeOption.loadSrc +
|
||||||
|
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
|
||||||
|
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
|
||||||
|
' componentId = ' + this.componentId)
|
||||||
|
ImageKnife.getInstance().execute(this.getRequest(
|
||||||
|
this.currentWidth, this.currentHeight, this.componentId))
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentContext(): common.UIAbilityContext {
|
getCurrentContext(): common.UIAbilityContext {
|
||||||
|
@ -103,43 +131,52 @@ export struct ImageKnifeAnimatorComponent {
|
||||||
return this.currentContext
|
return this.currentContext
|
||||||
}
|
}
|
||||||
|
|
||||||
getRequest(width: number, height: number): ImageKnifeRequest {
|
getRequest(width: number, height: number,componentId: number): ImageKnifeRequest {
|
||||||
if (this.request == undefined) {
|
this.request = new ImageKnifeRequest(
|
||||||
this.request = new ImageKnifeRequest(
|
this.imageKnifeOption,
|
||||||
this.imageKnifeOption,
|
this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
|
||||||
this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
|
width,
|
||||||
width,
|
height,
|
||||||
height,
|
this.componentVersion,
|
||||||
this.componentVersion,
|
{
|
||||||
{
|
showPixelMap: (version: number, pixelMap: PixelMap | string, size: Size, requestSource: ImageKnifeRequestSource,
|
||||||
showPixelMap: (version: number, pixelMap: PixelMap | string,size: Size, requestSource: ImageKnifeRequestSource,imageAnimator?: Array<ImageFrameInfo>) => {
|
imageAnimator?: Array<ImageFrameInfo>) => {
|
||||||
if (version !== this.componentVersion) {
|
if (version !== this.componentVersion) {
|
||||||
return //针对reuse场景,不显示历史图片
|
return //针对reuse场景,不显示历史图片
|
||||||
}
|
}
|
||||||
if (imageAnimator != undefined) {
|
if (imageAnimator != undefined) {
|
||||||
this.imageAnimator = imageAnimator
|
this.imageAnimator = imageAnimator
|
||||||
} else {
|
} else {
|
||||||
this.imageAnimator = [
|
this.imageAnimator = [
|
||||||
{
|
{
|
||||||
src: pixelMap
|
src: pixelMap
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
|
|
||||||
if (requestSource == ImageKnifeRequestSource.SRC) {
|
|
||||||
this.objectFit =
|
|
||||||
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
|
||||||
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
|
|
||||||
this.objectFit =
|
|
||||||
this.imageKnifeOption.placeholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.placeholderObjectFit
|
|
||||||
} else {
|
|
||||||
this.objectFit =
|
|
||||||
this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize == false &&
|
||||||
|
requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
|
this.adaptiveHeight = undefined
|
||||||
|
this.isImageFitAutoResize = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
|
this.objectFit =
|
||||||
|
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||||||
|
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
|
||||||
|
this.objectFit =
|
||||||
|
this.imageKnifeOption.placeholderObjectFit === undefined ?
|
||||||
|
(this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) :
|
||||||
|
this.imageKnifeOption.placeholderObjectFit
|
||||||
|
} else {
|
||||||
|
this.objectFit =
|
||||||
|
this.imageKnifeOption.errorholderObjectFit === undefined ?
|
||||||
|
(this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) :
|
||||||
|
this.imageKnifeOption.errorholderObjectFit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.request.animator = true
|
||||||
return this.request
|
return this.request
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,26 +20,29 @@ import { LogUtil } from '../utils/LogUtil';
|
||||||
import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData';
|
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';
|
||||||
|
import { emitter } from '@kit.BasicServicesKit';
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export struct ImageKnifeComponent {
|
export struct ImageKnifeComponent {
|
||||||
@Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
|
@Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
|
||||||
@State pixelMap: PixelMap | string | ImageContent | undefined = undefined
|
@State pixelMap: PixelMap | string | ImageContent | undefined = ImageContent.EMPTY
|
||||||
@State syncLoad: boolean = false
|
@State syncLoad: boolean = false
|
||||||
@State adaptiveWidth: Length = '100%'
|
@State adaptiveWidth: Length = '100%'
|
||||||
@State adaptiveHeight: Length = '100%'
|
@State adaptiveHeight: Length | undefined = '100%'
|
||||||
@State objectFit: ImageFit = ImageFit.Contain
|
@State objectFit: ImageFit = ImageFit.Contain
|
||||||
|
private componentId: number = 0
|
||||||
private request: ImageKnifeRequest | undefined
|
private request: ImageKnifeRequest | undefined
|
||||||
private lastWidth: number = 0
|
private lastWidth: number = 0
|
||||||
private lastHeight: number = 0
|
private lastHeight: number = 0
|
||||||
private currentWidth: number = 0
|
private currentWidth: number = 0
|
||||||
|
private isImageFitAutoResize: boolean = false
|
||||||
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
|
||||||
|
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
this.objectFit = (this.imageKnifeOption.objectFit === undefined || this.imageKnifeOption.objectFit === ImageFit.Auto) ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||||||
|
this.componentId = this.getUniqueId()
|
||||||
if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题,建议使用同步方式在aboutToAppear时加载图片
|
if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题,建议使用同步方式在aboutToAppear时加载图片
|
||||||
let engineKey: IEngineKey = new DefaultEngineKey();
|
let engineKey: IEngineKey = new DefaultEngineKey();
|
||||||
let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
|
let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
|
||||||
|
@ -64,13 +67,21 @@ export struct ImageKnifeComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToDisappear(): void {
|
aboutToDisappear(): void {
|
||||||
|
this.emitterDestroy()
|
||||||
this.clearLastRequest()
|
this.clearLastRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToRecycle() {
|
aboutToRecycle() {
|
||||||
this.pixelMap = ImageContent.EMPTY
|
this.pixelMap = ImageContent.EMPTY
|
||||||
|
this.emitterDestroy()
|
||||||
this.clearLastRequest()
|
this.clearLastRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitterDestroy() {
|
||||||
|
if (typeof this.request?.imageKnifeOption.loadSrc === 'string' && !this.request?.drawMainSuccess) {
|
||||||
|
emitter.emit(this.request.imageKnifeOption.loadSrc + this.componentId)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 对已DESTROY的组件不再发起请求
|
* 对已DESTROY的组件不再发起请求
|
||||||
*/
|
*/
|
||||||
|
@ -100,8 +111,18 @@ export struct ImageKnifeComponent {
|
||||||
} else {
|
} else {
|
||||||
// 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制
|
// 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制
|
||||||
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
|
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
|
||||||
LogUtil.log('execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight)
|
LogUtil.log('onSizeChange execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
|
||||||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
' loadSrc = ' + this.imageKnifeOption.loadSrc +
|
||||||
|
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
|
||||||
|
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
|
||||||
|
' componentId = ' + this.componentId)
|
||||||
|
|
||||||
|
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize) {
|
||||||
|
this.isImageFitAutoResize = false
|
||||||
|
} else {
|
||||||
|
ImageKnife.getInstance().execute(this.getRequest(
|
||||||
|
this.currentWidth, this.currentHeight, this.componentId))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -110,12 +131,15 @@ export struct ImageKnifeComponent {
|
||||||
watchImageKnifeOption() {
|
watchImageKnifeOption() {
|
||||||
this.clearLastRequest()
|
this.clearLastRequest()
|
||||||
this.componentVersion++
|
this.componentVersion++
|
||||||
|
this.isImageFitAutoResize = false
|
||||||
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||||||
LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight
|
LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
|
||||||
+ ' loadSrc = ' + this.request?.imageKnifeOption.loadSrc
|
' loadSrc = ' + this.imageKnifeOption.loadSrc +
|
||||||
+ ' placeholderSrc = ' + this.request?.imageKnifeOption.placeholderSrc
|
' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
|
||||||
+ ' errorholderSrc = ' + this.request?.imageKnifeOption.errorholderSrc)
|
' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
|
||||||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
' componentId = ' + this.componentId)
|
||||||
|
ImageKnife.getInstance().execute(this.getRequest(
|
||||||
|
this.currentWidth, this.currentHeight, this.componentId))
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentContext(): common.UIAbilityContext {
|
getCurrentContext(): common.UIAbilityContext {
|
||||||
|
@ -125,41 +149,41 @@ export struct ImageKnifeComponent {
|
||||||
return this.currentContext
|
return this.currentContext
|
||||||
}
|
}
|
||||||
|
|
||||||
getRequest(width: number, height: number): ImageKnifeRequest {
|
getRequest(width: number, height: number,componentId: number): ImageKnifeRequest {
|
||||||
if (this.request == undefined) {
|
this.request = new ImageKnifeRequest(
|
||||||
this.request = new ImageKnifeRequest(
|
this.imageKnifeOption,
|
||||||
this.imageKnifeOption,
|
this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
|
||||||
this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
|
width,
|
||||||
width,
|
height,
|
||||||
height,
|
this.componentVersion,
|
||||||
this.componentVersion,
|
{
|
||||||
{
|
showPixelMap: (version: number, pixelMap: PixelMap | string,size:Size, 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
|
LogUtil.info('image load showPixelMap:' + this.request?.componentId + ',srcType:' + requestSource +
|
||||||
if (typeof this.pixelMap !== 'string') {
|
',version:' + this.request?.componentVersion +
|
||||||
if (this.imageKnifeOption.objectFit === ImageFit.Auto) {
|
',size:' + JSON.stringify(size))
|
||||||
this.adaptiveWidth = this.currentWidth
|
if (this.imageKnifeOption.objectFit === ImageFit.Auto && this.isImageFitAutoResize == false && requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
this.adaptiveHeight = size.height * this.currentWidth / size.width
|
this.adaptiveHeight = undefined
|
||||||
}
|
this.isImageFitAutoResize = true
|
||||||
}
|
|
||||||
|
|
||||||
if (requestSource == ImageKnifeRequestSource.SRC) {
|
|
||||||
this.objectFit =
|
|
||||||
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
|
||||||
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
|
|
||||||
this.objectFit =
|
|
||||||
this.imageKnifeOption.placeholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.placeholderObjectFit
|
|
||||||
} else {
|
|
||||||
this.objectFit =
|
|
||||||
this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
|
this.objectFit =
|
||||||
|
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||||||
|
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
|
||||||
|
this.objectFit =
|
||||||
|
this.imageKnifeOption.placeholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.placeholderObjectFit
|
||||||
|
} else {
|
||||||
|
this.objectFit =
|
||||||
|
this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
componentId
|
||||||
|
)
|
||||||
return this.request
|
return this.request
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,23 @@ export class CenterInside implements BaseDownsampling {
|
||||||
return SampleSizeRounding.QUALITY
|
return SampleSizeRounding.QUALITY
|
||||||
}
|
}
|
||||||
//否则,使用 FIL_CENTER 的 SampleSizeRounding 值
|
//否则,使用 FIL_CENTER 的 SampleSizeRounding 值
|
||||||
return downsampType === DownsampleStrategy.CENTER_OUTSIDE_MEMORY?SampleSizeRounding.MEMORY:SampleSizeRounding.QUALITY
|
return downsampType === DownsampleStrategy.CENTER_INSIDE_MEMORY?SampleSizeRounding.MEMORY:SampleSizeRounding.QUALITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 默认值,图片分辨率超过上限7680 * 4320,宽高等比降为7680 * 4320
|
||||||
|
export class DefaultDownSampling implements BaseDownsampling {
|
||||||
|
getName(): string {
|
||||||
|
return 'DefaultDownSampling'
|
||||||
|
}
|
||||||
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number, downsampType?: DownsampleStrategy | undefined): number {
|
||||||
|
let resolution_max_8k = 7680 * 4320
|
||||||
|
let resolution_source = sourceWidth * sourceHeight
|
||||||
|
|
||||||
|
if ( resolution_source <= resolution_max_8k ) {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return resolution_source / resolution_max_8k
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,11 +154,13 @@ export enum DownsampleStrategy {
|
||||||
//两边自适应质量优先
|
//两边自适应质量优先
|
||||||
FIT_CENTER_QUALITY,
|
FIT_CENTER_QUALITY,
|
||||||
//按照宽高比的最大比进行适配内存优先
|
//按照宽高比的最大比进行适配内存优先
|
||||||
CENTER_OUTSIDE_MEMORY,
|
CENTER_INSIDE_MEMORY,
|
||||||
//按照宽高比的最大比进行适配质量优先
|
//按照宽高比的最大比进行适配质量优先
|
||||||
CENTER_OUTSIDE_QUALITY,
|
CENTER_INSIDE_QUALITY,
|
||||||
//宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配
|
//宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配
|
||||||
AT_LEAST,
|
AT_LEAST,
|
||||||
//不进行降采样
|
//不进行降采样
|
||||||
NONE,
|
NONE,
|
||||||
|
// 默认值,图片分辨率超过上限7680 * 4320,宽高等比降为7680 * 4320
|
||||||
|
DEFAULT
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@ import {
|
||||||
AtLeast,
|
AtLeast,
|
||||||
DownsampleStrategy,
|
DownsampleStrategy,
|
||||||
FitCenter,
|
FitCenter,
|
||||||
|
DefaultDownSampling,
|
||||||
} from './DownsampleStartegy';
|
} from './DownsampleStartegy';
|
||||||
export class Downsampler {
|
export class Downsampler {
|
||||||
calculateScaling(
|
calculateScaling(
|
||||||
|
@ -61,11 +62,13 @@ export class Downsampler {
|
||||||
return new FitCenter();
|
return new FitCenter();
|
||||||
case DownsampleStrategy.AT_MOST:
|
case DownsampleStrategy.AT_MOST:
|
||||||
return new AtMost();
|
return new AtMost();
|
||||||
case DownsampleStrategy.CENTER_OUTSIDE_MEMORY:
|
case DownsampleStrategy.CENTER_INSIDE_MEMORY:
|
||||||
case DownsampleStrategy.CENTER_OUTSIDE_QUALITY:
|
case DownsampleStrategy.CENTER_INSIDE_QUALITY:
|
||||||
return new CenterInside();
|
return new CenterInside();
|
||||||
case DownsampleStrategy.AT_LEAST:
|
case DownsampleStrategy.AT_LEAST:
|
||||||
return new AtLeast();
|
return new AtLeast();
|
||||||
|
case DownsampleStrategy.DEFAULT:
|
||||||
|
return new DefaultDownSampling();
|
||||||
default:
|
default:
|
||||||
throw new Error('Unsupported downsampling strategy');
|
throw new Error('Unsupported downsampling strategy');
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { FileCache } from '../cache/FileCache';
|
||||||
|
import { IImageLoaderStrategy } from './IImageLoaderStrategy';
|
||||||
|
import { ImageKnifeLoader } from '../ImageKnifeLoader';
|
||||||
|
import { ImageKnifeData, ImageKnifeRequestWithSource, RequestJobRequest, TimeInfo } from '../model/ImageKnifeData';
|
||||||
|
import { LoadPhase, LoadPixelMapCode } from '../utils/Constants';
|
||||||
|
import { LogUtil } from '../utils/LogUtil';
|
||||||
|
import List from '@ohos.util.List';
|
||||||
|
|
||||||
|
// 自定义加载策略
|
||||||
|
export class CustomLoaderStrategy implements IImageLoaderStrategy {
|
||||||
|
async loadImage(
|
||||||
|
request: RequestJobRequest,
|
||||||
|
requestList: List<ImageKnifeRequestWithSource> | undefined,
|
||||||
|
fileKey: string,
|
||||||
|
callBackData: ImageKnifeData,
|
||||||
|
callBackTimeInfo: TimeInfo
|
||||||
|
): Promise<void> {
|
||||||
|
let resBuf: ArrayBuffer | undefined;
|
||||||
|
let loadError: string = '';
|
||||||
|
|
||||||
|
// 从文件缓存获取
|
||||||
|
ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_CUSTOM_LOAD);
|
||||||
|
callBackTimeInfo.diskCheckStartTime = Date.now();
|
||||||
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey, request.fileCacheFolder);
|
||||||
|
callBackTimeInfo.diskCheckEndTime = Date.now();
|
||||||
|
|
||||||
|
if (resBuf !== undefined) {
|
||||||
|
ImageKnifeLoader.parseImage(resBuf, fileKey, request, callBackData);
|
||||||
|
} else if (!request.onlyRetrieveFromCache) {
|
||||||
|
LogUtil.log('start customGetImage src=' + request.componentId + ',srcType:' + request.requestSource + ',' +
|
||||||
|
request.componentVersion);
|
||||||
|
const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request);
|
||||||
|
try {
|
||||||
|
request.customGetImage!(request.context, request.src as string, headerObj)
|
||||||
|
.then((buffer)=>{
|
||||||
|
if(buffer !== undefined && buffer !== null) {
|
||||||
|
ImageKnifeLoader.FileCacheParseImage(request,buffer,fileKey,callBackData);
|
||||||
|
} else {
|
||||||
|
loadError = 'customGetImage loadFail undefined';
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request,loadError, ImageKnifeLoader.assembleError(callBackData,
|
||||||
|
LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE));
|
||||||
|
}
|
||||||
|
}).catch((err:string)=>{
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request,err, ImageKnifeLoader.assembleError(callBackData,
|
||||||
|
LoadPhase.PHASE_CUSTOM_LOAD, LoadPixelMapCode.IMAGE_CUSTOM_LOAD_FAILED_CODE));
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
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.componentId + ',srcType:' +
|
||||||
|
request.requestSource + ',' + request.componentVersion);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
loadError = `onlyRetrieveFromCache, do not fetch image src = ${request.src}`;
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError, callBackData);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { RequestJobRequest, ImageKnifeRequestWithSource, ImageKnifeData, TimeInfo } from '../model/ImageKnifeData';
|
||||||
|
import { IImageLoaderStrategy } from './IImageLoaderStrategy';
|
||||||
|
import List from '@ohos.util.List';
|
||||||
|
import { ImageKnifeLoader } from '../ImageKnifeLoader';
|
||||||
|
import { LoadPhase, LoadPixelMapCode } from '../utils/Constants';
|
||||||
|
import fs from '@ohos.file.fs';
|
||||||
|
|
||||||
|
export class FileLocalLoadStrategy implements IImageLoaderStrategy {
|
||||||
|
loadImage(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined, fileKey: string,
|
||||||
|
callBackData: ImageKnifeData, callBackTimeInfo: TimeInfo): Promise<void> {
|
||||||
|
let resBuf: ArrayBuffer | undefined;
|
||||||
|
let loadError: string = '';
|
||||||
|
if (typeof request.src === 'string' && ImageKnifeLoader.isLocalLoadSrc(request.context, request.src)) {
|
||||||
|
ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_LOCAL_FILE);
|
||||||
|
try {
|
||||||
|
const stat = fs.statSync(request.src);
|
||||||
|
if (stat.size > 0) {
|
||||||
|
const file = fs.openSync(request.src, fs.OpenMode.READ_ONLY);
|
||||||
|
resBuf = new ArrayBuffer(stat.size);
|
||||||
|
fs.readSync(file.fd, resBuf);
|
||||||
|
fs.closeSync(file);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_LOCAL_FILE,
|
||||||
|
LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE);
|
||||||
|
loadError = `LocalLoadSrc: ${request.src}, err: ${err}`;
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError,
|
||||||
|
ImageKnifeLoader.assembleError(
|
||||||
|
callBackData,
|
||||||
|
LoadPhase.PHASE_LOCAL_FILE,
|
||||||
|
LoadPixelMapCode.IMAGE_LOAD_LOCAL_FILE_FAILED_CODE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loadError = `Parameter not supported: ${request.src}`;
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError, callBackData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resBuf === undefined || resBuf === null) {
|
||||||
|
callBackTimeInfo.requestEndTime = Date.now();
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError, callBackData);
|
||||||
|
} else {
|
||||||
|
ImageKnifeLoader.parseImage(resBuf, fileKey, request, callBackData);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { ImageKnifeData, RequestJobRequest, TimeInfo, ImageKnifeRequestWithSource } from '../model/ImageKnifeData';
|
||||||
|
import fs from '@ohos.file.fs';
|
||||||
|
import { IImageLoaderStrategy } from './IImageLoaderStrategy';
|
||||||
|
import List from '@ohos.util.List';
|
||||||
|
import { ImageKnifeLoader } from '../ImageKnifeLoader';
|
||||||
|
import { LoadPhase, LoadPixelMapCode } from '../utils/Constants';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
|
||||||
|
export class FileSystemLoaderStrategy implements IImageLoaderStrategy {
|
||||||
|
async loadImage(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,
|
||||||
|
fileKey: string, callBackData: ImageKnifeData, callBackTimeInfo: TimeInfo
|
||||||
|
): Promise<void> {
|
||||||
|
let resBuf: ArrayBuffer | undefined;
|
||||||
|
let loadError: string = '';
|
||||||
|
|
||||||
|
if (typeof request.src === 'string' &&
|
||||||
|
(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.stat(file.fd).then(async (stat) => {
|
||||||
|
let buf = new ArrayBuffer(stat.size);
|
||||||
|
await fs.read(file.fd, buf).then((readLen) => {
|
||||||
|
resBuf = buf;
|
||||||
|
fs.closeSync(file.fd);
|
||||||
|
}).catch((err: BusinessError) => {
|
||||||
|
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) => {
|
||||||
|
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) => {
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (resBuf === undefined || resBuf === null) {
|
||||||
|
callBackTimeInfo.requestEndTime = Date.now();
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError, callBackData);
|
||||||
|
} else {
|
||||||
|
ImageKnifeLoader.parseImage(resBuf, fileKey, request, callBackData);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { FileCache } from '../cache/FileCache';
|
||||||
|
import { IImageLoaderStrategy } from './IImageLoaderStrategy';
|
||||||
|
import {
|
||||||
|
ImageKnifeData,
|
||||||
|
ImageKnifeRequestSource,
|
||||||
|
ImageKnifeRequestWithSource,
|
||||||
|
RequestJobRequest,
|
||||||
|
TimeInfo
|
||||||
|
} from '../model/ImageKnifeData';
|
||||||
|
import http from '@ohos.net.http';
|
||||||
|
import { ImageKnifeLoader } from '../ImageKnifeLoader';
|
||||||
|
import { combineArrayBuffers } from '../utils/ArrayBufferUtils';
|
||||||
|
import { BusinessError, emitter } from '@kit.BasicServicesKit';
|
||||||
|
import { Constants, LoadPhase, LoadPixelMapCode } from '../utils/Constants';
|
||||||
|
import { LogUtil } from '../utils/LogUtil';
|
||||||
|
import List from '@ohos.util.List';
|
||||||
|
|
||||||
|
class RequestData {
|
||||||
|
public receiveSize: number = 2000
|
||||||
|
public totalSize: number = 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP加载策略
|
||||||
|
export class HttpLoaderStrategy implements IImageLoaderStrategy {
|
||||||
|
async loadImage(
|
||||||
|
request: RequestJobRequest,
|
||||||
|
requestList: List<ImageKnifeRequestWithSource> | undefined,
|
||||||
|
fileKey: string,
|
||||||
|
callBackData: ImageKnifeData,
|
||||||
|
callBackTimeInfo: TimeInfo
|
||||||
|
): Promise<void> {
|
||||||
|
let resBuf: ArrayBuffer | undefined;
|
||||||
|
let loadError: string = '';
|
||||||
|
|
||||||
|
// 从文件缓存获取
|
||||||
|
ImageKnifeLoader.assembleError(callBackData, LoadPhase.PHASE_NET);
|
||||||
|
callBackTimeInfo.diskCheckStartTime = Date.now();
|
||||||
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey, request.fileCacheFolder);
|
||||||
|
callBackTimeInfo.diskCheckEndTime = Date.now();
|
||||||
|
|
||||||
|
if (resBuf !== undefined) {
|
||||||
|
LogUtil.log(`success get image from filecache for key = ${fileKey} src = ${request.componentId},
|
||||||
|
srcType:${request.requestSource}, ${request.componentVersion}`);
|
||||||
|
ImageKnifeLoader.parseImage(resBuf, fileKey, request, callBackData);
|
||||||
|
} else if (request.onlyRetrieveFromCache !== true) {
|
||||||
|
LogUtil.log(`HttpDownloadClient.start: ${request.componentId}, srcType:${request.requestSource},
|
||||||
|
${request.componentVersion}`);
|
||||||
|
callBackTimeInfo.netRequestStartTime = Date.now();
|
||||||
|
const httpRequest = http.createHttp();
|
||||||
|
emitter.once((request.src as string) + request.componentId,()=>{
|
||||||
|
httpRequest.destroy()
|
||||||
|
})
|
||||||
|
let progress: number = 0;
|
||||||
|
const arrayBuffers: ArrayBuffer[] = [];
|
||||||
|
const headerObj: Record<string, Object> = ImageKnifeLoader.getHeaderObj(request);
|
||||||
|
|
||||||
|
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
|
||||||
|
arrayBuffers.push(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (request.isWatchProgress) {
|
||||||
|
httpRequest.on('dataReceiveProgress', (data: RequestData) => {
|
||||||
|
if (data != undefined && typeof data.receiveSize === 'number' && typeof data.totalSize === 'number') {
|
||||||
|
const percent = Math.round(((data.receiveSize * 1.0) / (data.totalSize * 1.0)) * 100);
|
||||||
|
if (progress !== percent) {
|
||||||
|
progress = percent;
|
||||||
|
if (requestList === undefined) {
|
||||||
|
// 子线程
|
||||||
|
emitter.emit(Constants.PROGRESS_EMITTER + request.memoryKey, { data: { 'value': progress } });
|
||||||
|
} else {
|
||||||
|
// 主线程请求
|
||||||
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
|
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined &&
|
||||||
|
requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
||||||
|
requestWithSource.request.imageKnifeOption.progressListener(progress);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let promise = httpRequest.requestInStream(request.src as string, {
|
||||||
|
header: headerObj,
|
||||||
|
method: http.RequestMethod.GET,
|
||||||
|
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
||||||
|
connectTimeout: request.connectTimeout ?? 60000,
|
||||||
|
readTimeout: request.readTimeout ?? 30000,
|
||||||
|
caPath: request.caPath
|
||||||
|
});
|
||||||
|
promise.then((data: number) => {
|
||||||
|
emitter.off((request.src as string) + request.componentId)
|
||||||
|
callBackData.httpCode = data;
|
||||||
|
ImageKnifeLoader.assembleError(callBackData,LoadPhase.PHASE_NET, undefined);
|
||||||
|
callBackTimeInfo.netRequestEndTime = Date.now();
|
||||||
|
if (data == 200 || data == 206 || data == 204) {
|
||||||
|
resBuf = combineArrayBuffers(arrayBuffers);
|
||||||
|
ImageKnifeLoader.FileCacheParseImage(request,resBuf,fileKey, callBackData);
|
||||||
|
} else {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}).catch((err: BusinessError) => {
|
||||||
|
emitter.off((request.src as string) + request.componentId)
|
||||||
|
callBackData.httpCode = err.code;
|
||||||
|
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));
|
||||||
|
});
|
||||||
|
LogUtil.log('HttpDownloadClient.end:' + request.componentId + ',srcType:' +
|
||||||
|
request.requestSource + ',' + request.componentVersion);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
callBackTimeInfo.netRequestEndTime = Date.now();
|
||||||
|
loadError = `onlyRetrieveFromCache, do not fetch image src = ${request.src}`;
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError, callBackData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { ImageKnifeData, ImageKnifeRequestWithSource, RequestJobRequest, TimeInfo } from '../model/ImageKnifeData';
|
||||||
|
import List from '@ohos.util.List';
|
||||||
|
|
||||||
|
// 定义图片加载策略接口
|
||||||
|
export interface IImageLoaderStrategy {
|
||||||
|
loadImage(
|
||||||
|
request: RequestJobRequest,
|
||||||
|
requestList: List<ImageKnifeRequestWithSource> | undefined,
|
||||||
|
fileKey: string,
|
||||||
|
callBackData: ImageKnifeData,
|
||||||
|
callBackTimeInfo: TimeInfo
|
||||||
|
): Promise<void>;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { CustomLoaderStrategy } from './CustomLoaderStrategy';
|
||||||
|
import { FileSystemLoaderStrategy } from './FileSystemLoaderStrategy';
|
||||||
|
import { HttpLoaderStrategy } from './HttpLoaderStrategy';
|
||||||
|
import { IImageLoaderStrategy } from './IImageLoaderStrategy';
|
||||||
|
import { ImageKnifeRequestSource, RequestJobRequest } from '../model/ImageKnifeData';
|
||||||
|
import { ResourceLoaderStrategy } from './ResourceLoaderStrategy';
|
||||||
|
import { FileLocalLoadStrategy } from './FileLocalLoadStrategy';
|
||||||
|
|
||||||
|
export class ImageLoaderFactory {
|
||||||
|
static getLoaderStrategy(request: RequestJobRequest): IImageLoaderStrategy | null {
|
||||||
|
if (request.customGetImage !== undefined &&
|
||||||
|
request.requestSource === ImageKnifeRequestSource.SRC &&
|
||||||
|
typeof request.src === 'string'
|
||||||
|
) {
|
||||||
|
return new CustomLoaderStrategy();
|
||||||
|
} else if (typeof request.src === 'string') {
|
||||||
|
if (request.src.startsWith('http://') || request.src.startsWith('https://')) {
|
||||||
|
return new HttpLoaderStrategy();
|
||||||
|
} else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) {
|
||||||
|
return new FileSystemLoaderStrategy();
|
||||||
|
} else {
|
||||||
|
return new FileLocalLoadStrategy();
|
||||||
|
}
|
||||||
|
} else if (typeof request.src === 'number') {
|
||||||
|
return new ResourceLoaderStrategy();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 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 { IImageLoaderStrategy } from './IImageLoaderStrategy';
|
||||||
|
import {
|
||||||
|
ImageKnifeData,
|
||||||
|
ImageKnifeRequestSource,
|
||||||
|
ImageKnifeRequestWithSource,
|
||||||
|
RequestJobRequest,
|
||||||
|
TimeInfo
|
||||||
|
} from '../model/ImageKnifeData';
|
||||||
|
import List from '@ohos.util.List';
|
||||||
|
import { application } from '@kit.AbilityKit';
|
||||||
|
import { ImageKnifeLoader } from '../ImageKnifeLoader';
|
||||||
|
|
||||||
|
export class ResourceLoaderStrategy implements IImageLoaderStrategy {
|
||||||
|
async loadImage(
|
||||||
|
request: RequestJobRequest,
|
||||||
|
requestList: List<ImageKnifeRequestWithSource> | undefined,
|
||||||
|
fileKey: string,
|
||||||
|
callBackData: ImageKnifeData,
|
||||||
|
callBackTimeInfo: TimeInfo
|
||||||
|
): Promise<void> {
|
||||||
|
let resBuf: ArrayBuffer | undefined;
|
||||||
|
let loadError: string = '';
|
||||||
|
|
||||||
|
if (typeof request.src === 'number') {
|
||||||
|
const moduleContext = await application.createModuleContext(request.context, request.moduleName);
|
||||||
|
const manager = moduleContext.resourceManager;
|
||||||
|
if ((resBuf == undefined && request.onlyRetrieveFromCache !== true &&
|
||||||
|
request.requestSource === ImageKnifeRequestSource.SRC) ||
|
||||||
|
(resBuf == undefined && request.requestSource !== ImageKnifeRequestSource.SRC)) {
|
||||||
|
if (request.src === -1) {
|
||||||
|
const resName = request.resName as string;
|
||||||
|
resBuf =
|
||||||
|
(await manager.getMediaByName(resName.substring(resName.lastIndexOf('.') + 1))).buffer as ArrayBuffer;
|
||||||
|
} else {
|
||||||
|
resBuf = request.resName ?
|
||||||
|
manager.getRawFileContentSync(request.resName).buffer.slice(0) :
|
||||||
|
(manager.getMediaContentSync(request.src)).buffer as ArrayBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resBuf === undefined || resBuf === null){
|
||||||
|
callBackTimeInfo.requestEndTime = Date.now();
|
||||||
|
loadError = 'Resource load error';
|
||||||
|
ImageKnifeLoader.makeEmptyResult(request, loadError ,callBackData);
|
||||||
|
} else {
|
||||||
|
ImageKnifeLoader.parseImage(resBuf,fileKey,request, callBackData);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ export interface ImageKnifeData {
|
||||||
imageHeight: number,
|
imageHeight: number,
|
||||||
bufSize?: number, // 图片的字节数
|
bufSize?: number, // 图片的字节数
|
||||||
type?:string,
|
type?:string,
|
||||||
|
httpCode?: number, // 网络请求状态码及错误码
|
||||||
imageAnimator?: Array<ImageFrameInfo>
|
imageAnimator?: Array<ImageFrameInfo>
|
||||||
frameCount ?: number // 帧
|
frameCount ?: number // 帧
|
||||||
decodeImages?: Array<DecodeImageInfo> //Image组件或者ImageAnimator组件可以加载一张或者多张
|
decodeImages?: Array<DecodeImageInfo> //Image组件或者ImageAnimator组件可以加载一张或者多张
|
||||||
|
@ -48,7 +49,6 @@ export interface DecodeImageInfo {
|
||||||
export interface ErrorInfo {
|
export interface ErrorInfo {
|
||||||
phase: string, //图片加载阶段信息,如:网络加载阶段,缓存获取阶段及其解码阶段等
|
phase: string, //图片加载阶段信息,如:网络加载阶段,缓存获取阶段及其解码阶段等
|
||||||
code: number,
|
code: number,
|
||||||
httpCode?: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,6 +150,17 @@ export interface RequestJobRequest {
|
||||||
caPath?: string,
|
caPath?: string,
|
||||||
targetWidth: number
|
targetWidth: number
|
||||||
targetHeight: number
|
targetHeight: number
|
||||||
downsampType: DownsampleStrategy
|
downsampType: DownsampleStrategy,
|
||||||
|
isAutoImageFit: boolean,
|
||||||
|
componentId?: number,
|
||||||
|
componentVersion?: number
|
||||||
|
connectTimeout?: number
|
||||||
|
readTimeout?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FlipRotate{
|
||||||
|
horizontal: boolean,
|
||||||
|
vertical: boolean,
|
||||||
|
rotate: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,10 @@ export class AnimatorOption {
|
||||||
onRepeat?:()=>void
|
onRepeat?:()=>void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImageOption {
|
export interface HttpRequestOption {
|
||||||
// 自定义证书路径
|
caPath?: string // 自定义证书路径
|
||||||
caPath?: string,
|
connectTimeout?: number // 连接超时
|
||||||
|
readTimeout?: number // 读取超时
|
||||||
}
|
}
|
||||||
@Observed
|
@Observed
|
||||||
export class ImageKnifeOption {
|
export class ImageKnifeOption {
|
||||||
|
@ -81,7 +82,7 @@ export class ImageKnifeOption {
|
||||||
drawingColorFilter?: ColorFilter | drawing.ColorFilter
|
drawingColorFilter?: ColorFilter | drawing.ColorFilter
|
||||||
downsampleOf?: DownsampleStrategy // 降采样
|
downsampleOf?: DownsampleStrategy // 降采样
|
||||||
// 自定义证书路径
|
// 自定义证书路径
|
||||||
caPath?: string
|
httpOption?: HttpRequestOption
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,24 +22,28 @@ export class ImageKnifeRequest {
|
||||||
componentWidth: number = 0
|
componentWidth: number = 0
|
||||||
componentHeight: number = 0
|
componentHeight: number = 0
|
||||||
drawPlayHolderSuccess: boolean = false
|
drawPlayHolderSuccess: boolean = false
|
||||||
|
drawMainSuccess: boolean = false
|
||||||
imageKnifeOption: ImageKnifeOption
|
imageKnifeOption: ImageKnifeOption
|
||||||
context: common.UIAbilityContext
|
context: common.UIAbilityContext
|
||||||
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>()
|
||||||
imageKnifeData?: ImageKnifeData
|
imageKnifeData?: ImageKnifeData
|
||||||
|
componentId?: number
|
||||||
|
animator?: boolean
|
||||||
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,componentId?: number) {
|
||||||
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.componentId = componentId
|
||||||
}
|
}
|
||||||
// RequestOption调用header对于的方法
|
// RequestOption调用header对于的方法
|
||||||
addHeader(key: string, value: Object) {
|
addHeader(key: string, value: Object) {
|
||||||
|
|
|
@ -56,11 +56,12 @@ export class CropTransformation extends PixelMapTransformation {
|
||||||
let scaledWidth: number = scale * pixelMapWidth;
|
let scaledWidth: number = scale * pixelMapWidth;
|
||||||
let scaledHeight: number = scale * pixelMapHeight;
|
let scaledHeight: number = scale * pixelMapHeight;
|
||||||
let left: number = (this.mWidth - scaledWidth) / 2;
|
let left: number = (this.mWidth - scaledWidth) / 2;
|
||||||
let top: number = Math.abs(this.getTop(pixelMapHeight));
|
let top: number = Math.abs(this.getTop(scaledHeight));
|
||||||
|
toTransform.scaleSync(scale,scale)
|
||||||
let region: image.Region = {
|
let region: image.Region = {
|
||||||
size: {
|
size: {
|
||||||
width: scaledWidth > pixelMapWidth ? pixelMapWidth : scaledWidth,
|
width: this.mWidth,
|
||||||
height: scaledHeight > pixelMapHeight ? pixelMapHeight : scaledHeight
|
height: this.mHeight
|
||||||
},
|
},
|
||||||
x: left < 0 ? 0 : left,
|
x: left < 0 ? 0 : left,
|
||||||
y: top < 0 ? 0 : top
|
y: top < 0 ? 0 : top
|
||||||
|
|
|
@ -86,6 +86,7 @@ export class MaskTransformation extends PixelMapTransformation {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let maskBitmap: PixelMap = await imageSource.createPixelMap(options);
|
let maskBitmap: PixelMap = await imageSource.createPixelMap(options);
|
||||||
|
imageSource.release()
|
||||||
return await this.mask(bitmap, maskBitmap);
|
return await this.mask(bitmap, maskBitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,10 @@ export class FileTypeUtil {
|
||||||
'bmp': [new Uint8Array([0x42, 0x4D])],
|
'bmp': [new Uint8Array([0x42, 0x4D])],
|
||||||
'svg': [new Uint8Array([0x3C, 0x3F, 0x78, 0x6D, 0x6C]),new Uint8Array([0x3C, 0x73, 0x76, 0x67, 0x20])],
|
'svg': [new Uint8Array([0x3C, 0x3F, 0x78, 0x6D, 0x6C]),new Uint8Array([0x3C, 0x73, 0x76, 0x67, 0x20])],
|
||||||
'webp': [new Uint8Array([0x52, 0x49, 0x46, 0x46])],
|
'webp': [new Uint8Array([0x52, 0x49, 0x46, 0x46])],
|
||||||
|
'ico': [new Uint8Array([0x00,0x00,0x01,0x00])],
|
||||||
'tiff': [new Uint8Array([0x49, 0x20, 0x49]), new Uint8Array([0x49, 0x49, 0x2A, 0x00]), new Uint8Array([0x4D, 0x4D, 0x00, 0x2A]), new Uint8Array([0x4D, 0x4D, 0x00, 0x2B])],
|
'tiff': [new Uint8Array([0x49, 0x20, 0x49]), new Uint8Array([0x49, 0x49, 0x2A, 0x00]), new Uint8Array([0x4D, 0x4D, 0x00, 0x2A]), new Uint8Array([0x4D, 0x4D, 0x00, 0x2B])],
|
||||||
// 添加更多的文件类型和特征
|
// 添加更多的文件类型和特征
|
||||||
'heic': [new Uint8Array([0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00]),new Uint8Array([0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00])],
|
'heic': [new Uint8Array([0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63]),new Uint8Array([0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x6D, 0x69, 0x66, 0x31])],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +43,8 @@ export class FileTypeUtil {
|
||||||
value == SupportFormat.bmp ||
|
value == SupportFormat.bmp ||
|
||||||
value == SupportFormat.gif ||
|
value == SupportFormat.gif ||
|
||||||
value == SupportFormat.svg ||
|
value == SupportFormat.svg ||
|
||||||
value == SupportFormat.heic
|
value == SupportFormat.heic ||
|
||||||
|
value == SupportFormat.ico
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -108,5 +110,6 @@ export enum SupportFormat {
|
||||||
gif = 'gif',
|
gif = 'gif',
|
||||||
svg = 'svg',
|
svg = 'svg',
|
||||||
tiff = 'tiff',
|
tiff = 'tiff',
|
||||||
heic = 'heic'
|
heic = 'heic',
|
||||||
|
ico = 'ico'
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,6 @@ export class FileUtils {
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async deleteFile(path: string): Promise<void> {
|
async deleteFile(path: string): Promise<void> {
|
||||||
// const isExist: boolean = await fs.access(path)
|
|
||||||
// if (isExist) {
|
|
||||||
try {
|
try {
|
||||||
await fs.unlink(path)
|
await fs.unlink(path)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -76,8 +74,7 @@ export class FileUtils {
|
||||||
writeDataSync(path: string, content: ArrayBuffer | string): boolean {
|
writeDataSync(path: string, content: ArrayBuffer | string): boolean {
|
||||||
try {
|
try {
|
||||||
let fd = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC).fd
|
let fd = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC).fd
|
||||||
let stat = fs.statSync(path)
|
fs.writeSync(fd, content)
|
||||||
fs.writeSync(fd, content, { offset: stat.size })
|
|
||||||
fs.closeSync(fd)
|
fs.closeSync(fd)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -150,9 +147,9 @@ export class FileUtils {
|
||||||
readFileSync(path: string): ArrayBuffer | undefined {
|
readFileSync(path: string): ArrayBuffer | undefined {
|
||||||
try {
|
try {
|
||||||
if (fs.accessSync(path)) {
|
if (fs.accessSync(path)) {
|
||||||
let fd = fs.openSync(path, fs.OpenMode.READ_ONLY).fd;
|
|
||||||
let length = fs.statSync(path).size
|
let length = fs.statSync(path).size
|
||||||
let buf = new ArrayBuffer(length);
|
let buf = new ArrayBuffer(length);
|
||||||
|
let fd = fs.openSync(path, fs.OpenMode.READ_ONLY).fd;
|
||||||
fs.readSync(fd, buf)
|
fs.readSync(fd, buf)
|
||||||
fs.closeSync(fd)
|
fs.closeSync(fd)
|
||||||
return buf
|
return buf
|
||||||
|
|
|
@ -17,17 +17,25 @@ import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||||
export class LogUtil {
|
export class LogUtil {
|
||||||
public static readonly DOMAIN: number = 0xD002220;
|
public static readonly DOMAIN: number = 0xD002220;
|
||||||
public static readonly TAG: string = 'ImageKnife::';
|
public static readonly TAG: string = 'ImageKnife::';
|
||||||
|
public static ON: boolean = true
|
||||||
|
public static OFF: boolean = false
|
||||||
|
public static mLogLevel:boolean = LogUtil.ON
|
||||||
public static debug(message: string, ...args: Object[]) {
|
public static debug(message: string, ...args: Object[]) {
|
||||||
hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
if (LogUtil.mLogLevel == LogUtil.ON) {
|
||||||
|
hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static info(message: string, ...args: Object[]) {
|
public static info(message: string, ...args: Object[]) {
|
||||||
hilog.info(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
if (LogUtil.mLogLevel == LogUtil.ON) {
|
||||||
|
hilog.info(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static log(message: string, ...args: Object[]) {
|
public static log(message: string, ...args: Object[]) {
|
||||||
hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
if (LogUtil.mLogLevel == LogUtil.ON) {
|
||||||
|
hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static warn(message: string, ...args: Object[]) {
|
public static warn(message: string, ...args: Object[]) {
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
"deviceTypes": [
|
"deviceTypes": [
|
||||||
"default",
|
"default",
|
||||||
"tablet",
|
"tablet",
|
||||||
|
"tv",
|
||||||
|
"wearable",
|
||||||
|
"car",
|
||||||
"2in1"
|
"2in1"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"modelVersion": "5.0.1",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohos/hypium": "1.0.6"
|
"@ohos/hypium": "1.0.6"
|
||||||
|
@ -8,4 +9,4 @@
|
||||||
"repository": {},
|
"repository": {},
|
||||||
"version": "",
|
"version": "",
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ export { ImageKnifeComponent,ImageKnifeAnimatorComponent } from '@ohos/imageknif
|
||||||
|
|
||||||
export { ImageKnife } from '@ohos/imageknife'
|
export { ImageKnife } from '@ohos/imageknife'
|
||||||
|
|
||||||
export { ImageKnifeOption,AnimatorOption } from '@ohos/imageknife'
|
export { ImageKnifeOption, AnimatorOption, HttpRequestOption, HeaderOptions } from '@ohos/imageknife'
|
||||||
|
|
||||||
export { DownsampleStrategy } from "@ohos/imageknife"
|
export { DownsampleStrategy } from "@ohos/imageknife"
|
||||||
|
|
||||||
|
|
|
@ -15,4 +15,7 @@
|
||||||
|
|
||||||
# Keep options:
|
# Keep options:
|
||||||
# -keep-property-name: specifies property names that you want to keep
|
# -keep-property-name: specifies property names that you want to keep
|
||||||
# -keep-global-name: specifies names that you want to keep in the global scope
|
# -keep-global-name: specifies names that you want to keep in the global scope
|
||||||
|
|
||||||
|
-keep
|
||||||
|
./oh_modules/@ohos/imageknife
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "sharedlibrary",
|
"name": "@ohos/libraryimageknife",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Please describe the basic information.",
|
"description": "Please describe the basic information.",
|
||||||
"main": "Index.ets",
|
"main": "Index.ets",
|
||||||
|
|
|
@ -4,8 +4,11 @@
|
||||||
"type": "shared",
|
"type": "shared",
|
||||||
"description": "$string:shared_desc",
|
"description": "$string:shared_desc",
|
||||||
"deviceTypes": [
|
"deviceTypes": [
|
||||||
"phone",
|
"default",
|
||||||
"tablet",
|
"tablet",
|
||||||
|
"tv",
|
||||||
|
"wearable",
|
||||||
|
"car",
|
||||||
"2in1"
|
"2in1"
|
||||||
],
|
],
|
||||||
"deliveryWithInstall": true,
|
"deliveryWithInstall": true,
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
"description": "$string:module_test_desc",
|
"description": "$string:module_test_desc",
|
||||||
"mainElement": "TestAbility",
|
"mainElement": "TestAbility",
|
||||||
"deviceTypes": [
|
"deviceTypes": [
|
||||||
"phone",
|
"default",
|
||||||
"tablet",
|
"tablet"
|
||||||
"2in1"
|
|
||||||
],
|
],
|
||||||
"deliveryWithInstall": true,
|
"deliveryWithInstall": true,
|
||||||
"installationFree": false,
|
"installationFree": false,
|
||||||
|
|
Loading…
Reference in New Issue