3.x分支更新3.1.0版本代码,并且删除适配componentV2装饰器提交
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
This commit is contained in:
parent
ccd4455b83
commit
a3ed45a468
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,3 +1,15 @@
|
||||||
|
## 3.0.2
|
||||||
|
- ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件
|
||||||
|
- 文件缓存数量负数和超过INT最大值时默认为INT最大值
|
||||||
|
- 修复宽高不等svg图片显示有毛边
|
||||||
|
- 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别
|
||||||
|
- 修复加载错误图后未去请求排队队列中的请求
|
||||||
|
- 子线程本地Resource参数类型转换成number
|
||||||
|
- 修改使用hilog记录日志,默认打开debug级别的日志
|
||||||
|
- 解码pixelMap默认不可编辑,图形变化可编辑
|
||||||
|
- 修改网络请求超时设置
|
||||||
|
- 重构代码:抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中,降低函数复杂度
|
||||||
|
|
||||||
## 3.0.2-rc.1
|
## 3.0.2-rc.1
|
||||||
- release打包关闭混淆
|
- release打包关闭混淆
|
||||||
|
|
||||||
|
|
344
README.md
344
README.md
|
@ -1,229 +1,228 @@
|
||||||
# ImageKnife
|
# ImageKnife
|
||||||
|
|
||||||
**专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。**
|
ImageKnife is a specially crafted image loading and caching library for OpenHarmony, optimized for efficiency, lightness, and simplicity.
|
||||||
|
|
||||||
## 简介
|
## Introduction
|
||||||
|
|
||||||
本项目参考开源库 [Glide](https://github.com/bumptech/glide) 进行OpenHarmony的自研版本:
|
This project is a self-developed version for OpenHarmony, inspired by the open-source [Glide](https://github.com/bumptech/glide) library. It sports the following features:
|
||||||
|
|
||||||
- 支持自定义内存缓存策略,支持设置内存缓存的大小(默认LRU策略)。
|
- Customizable memory cache strategy with adjustable cache size (default LRU)
|
||||||
- 支持磁盘二级缓存,对于下载图片会保存一份至磁盘当中。
|
- Disk L2 cache for downloaded images
|
||||||
- 支持自定义实现图片获取/网络下载
|
- Custom implementation for image acquisition and network downloading
|
||||||
- 支持监听网络下载回调进度
|
- Listening for progress of network downloads through callbacks
|
||||||
- 继承Image的能力,支持option传入border,设置边框,圆角
|
- Image options for borders and rounded corners
|
||||||
- 继承Image的能力,支持option传入objectFit设置图片缩放,包括objectFit为auto时根据图片自适应高度
|
- Image scaling with **objectFit**, including auto-adapting height
|
||||||
- 支持通过设置transform缩放图片
|
- Image scaling through transformation
|
||||||
- 并发请求数量,支持请求排队队列的优先级
|
- Concurrent request management with priority queuing
|
||||||
- 支持生命周期已销毁的图片,不再发起请求
|
- No requests made for images whose lifecycle has been destroyed
|
||||||
- 自定义缓存key
|
- Custom cache keys
|
||||||
- 自定义http网络请求头
|
- Custom HTTP request headers
|
||||||
- 支持writeCacheStrategy控制缓存的存入策略(只存入内存或文件缓存)
|
- **writeCacheStrategy** for controlling cache storage (memory or file)
|
||||||
- 支持preLoadCache预加载图片
|
- Preloading images with **preLoadCache**
|
||||||
- 支持onlyRetrieveFromCache仅用缓存加载
|
- Loading images exclusively from cache with **onlyRetrieveFromCache**
|
||||||
- 支持使用一个或多个图片变换,如模糊,高亮等
|
- Support for image transformations such as blurring and highlighting
|
||||||
|
|
||||||
待实现特性
|
Planned features:
|
||||||
|
|
||||||
- gif/webp动图显示与控制
|
- Memory downsampling optimization to save memory usage
|
||||||
- 内存降采样优化,节约内存的占用
|
- Support for custom image decoding
|
||||||
- 支持自定义图片解码
|
|
||||||
|
|
||||||
注意:3.x版本相对2.x版本做了重大的重构,主要体现在:
|
Note: The 3.x version has been significantly restructured from the 2.x version, mainly in the following aspects:
|
||||||
|
|
||||||
- 使用Image组件代替Canvas组件渲染
|
- Use of the **Image** component instead of the **Canvas** component for rendering
|
||||||
- 重构Dispatch分发逻辑,支持控制并发请求数,支持请求排队队列的优先级
|
- Refactored dispatch logic to control the number of concurrent requests and support priority in request queuing
|
||||||
- 支持通过initMemoryCache自定义策略内存缓存策略和大小
|
- Support for custom memory cache strategies and sizes through **initMemoryCache**
|
||||||
- 支持option自定义实现图片获取/网络下载
|
- Support for custom implementation of image acquisition/network downloading through options
|
||||||
|
|
||||||
因此API及能力上,目前有部分差异,主要体现在:
|
Therefore, there are some differences in APIs and capabilities, which mainly include the following:
|
||||||
|
|
||||||
- 不支持drawLifeCycle接口,通过canvas自会图片
|
- The **drawLifeCycle** API is not supported; images are drawn manually through the canvas.
|
||||||
- mainScaleType,border等参数,新版本与系统Image保持一致
|
- In the new version, parameters such as **mainScaleType** and **border** are consistent with the system **Image** component.
|
||||||
- gif/webp动图播放与控制
|
- GIF/WebP animation playback and control (implemented by **ImageAnimator**).
|
||||||
- 抗锯齿相关参数
|
- Anti-aliasing related parameters.
|
||||||
|
|
||||||
## 下载安装
|
## How to Install
|
||||||
|
|
||||||
```
|
```
|
||||||
ohpm install @ohos/imageknife
|
ohpm install @ohos/imageknife
|
||||||
|
|
||||||
// 如果需要用文件缓存,需要提前初始化文件缓存
|
// If file caching is required, initialize the file cache in advance.
|
||||||
await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
|
await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用说明
|
## How to Use
|
||||||
|
|
||||||
#### 1.显示本地资源图片
|
#### 1. Displaying a Local Resource Image
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
ImageKnifeOption: {
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc: $r("app.media.app_icon"),
|
loadSrc: $r("app.media.app_icon"),
|
||||||
placeholderSrc: $r("app.media.loading"),
|
placeholderSrc: $r("app.media.loading"),
|
||||||
errorholderSrc: $r("app.media.app_icon"),
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
objectFit: ImageFit.Auto
|
objectFit: ImageFit.Auto
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2.显示本地context files下文件
|
#### 2. Displaying a File from Local Context Files
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
ImageKnifeOption: {
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc: this.localFile,
|
loadSrc: this.localFile,
|
||||||
placeholderSrc: $r("app.media.loading"),
|
placeholderSrc: $r("app.media.loading"),
|
||||||
errorholderSrc: $r("app.media.app_icon"),
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
objectFit: ImageFit.Auto
|
objectFit: ImageFit.Auto
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 3.显示网络图片
|
#### 3. Displaying a Network Image
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
ImageKnifeOption: {
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
|
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
|
||||||
placeholderSrc: $r("app.media.loading"),
|
placeholderSrc: $r("app.media.loading"),
|
||||||
errorholderSrc: $r("app.media.app_icon"),
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
objectFit: ImageFit.Auto
|
objectFit: ImageFit.Auto
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4.自定义下载图片
|
#### 4. Downloading an Image with Custom Options
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
ImageKnifeOption: {
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
|
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
|
||||||
placeholderSrc: $r("app.media.loading"),
|
placeholderSrc: $r("app.media.loading"),
|
||||||
errorholderSrc: $r("app.media.app_icon"),
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
objectFit: ImageFit.Auto,
|
objectFit: ImageFit.Auto,
|
||||||
customGetImage: custom
|
customGetImage: custom
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
|
|
||||||
// 自定义实现图片获取方法,如自定义网络下载
|
// Custom implementation of the image acquisition method, such as custom network download。
|
||||||
@Concurrent
|
@Concurrent
|
||||||
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> {
|
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> {
|
||||||
console.info("ImageKnife:: custom download:" + src)
|
console.info("ImageKnife:: custom download: " + src)
|
||||||
// 举例写死从本地文件读取,也可以自己请求网络图片
|
// Example of hardcoding to read from a local file. You can also request a network image.
|
||||||
return context.resourceManager.getMediaContentSync($r("app.media.bb").id).buffer as ArrayBuffer
|
return context.resourceManager.getMediaContentSync($r("app.media.bb").id).buffer as ArrayBuffer
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5.监听网络下载进度
|
#### 5. Listening for Network Download Progress
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
ImageKnifeOption: {
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
|
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
|
||||||
progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)}
|
progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)}
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 6.支持option传入border,设置边框,圆角
|
#### 6. Setting Border Options
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({ ImageKnifeOption:
|
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
|
||||||
{
|
{
|
||||||
loadSrc: $r("app.media.rabbit"),
|
loadSrc: $r("app.media.rabbit"),
|
||||||
border: {radius:50}
|
border: {radius:50}
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 7.支持option图片变换
|
#### 7. Setting Image Transformation Options
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({ ImageKnifeOption:
|
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
|
||||||
{
|
{
|
||||||
loadSrc: $r("app.media.rabbit"),
|
loadSrc: $r("app.media.rabbit"),
|
||||||
border: {radius:50},
|
border: {radius:50},
|
||||||
transformation: new BlurTransformation(3)
|
transformation: new BlurTransformation(3)
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
多种组合变换用法
|
Multiple combined transformation usages:
|
||||||
|
|
||||||
```
|
```
|
||||||
let transformations: collections.Array<PixelMapTransformation> = new collections.Array<PixelMapTransformation>();
|
let transformations: collections.Array<PixelMapTransformation> = new collections.Array<PixelMapTransformation>();
|
||||||
transformations.push(new BlurTransformation(5));
|
transformations.push(new BlurTransformation(5));
|
||||||
transformations.push(new BrightnessTransformation(0.2));
|
transformations.push(new BrightnessTransformation(0.2));
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
{
|
imageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc: $r('app.media.pngSample'),
|
loadSrc: $r('app.media.pngSample'),
|
||||||
placeholderSrc: $r("app.media.loading"),
|
placeholderSrc: $r("app.media.loading"),
|
||||||
errorholderSrc: $r("app.media.app_icon"),
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
objectFit: ImageFit.Contain,
|
objectFit: ImageFit.Contain,
|
||||||
border: { radius: { topLeft: 50, bottomRight: 50 } }, // 圆角设置
|
border: { radius: { topLeft: 50, bottomRight: 50 } }, // Rounded corner settings
|
||||||
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // 图形变换组
|
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // Graphic transformation group
|
||||||
}
|
})
|
||||||
}).width(300)
|
}).width(300)
|
||||||
.height(300)
|
.height(300)
|
||||||
.rotate({ angle: 90 }) // 旋转90度
|
.rotate ({angle: 90}) // Rotate by 90 degrees.
|
||||||
.contrast(12) // 对比度滤波器
|
.contrast(12) // Contrast filter
|
||||||
```
|
```
|
||||||
其他变换相关属性,可叠加实现组合变换效果
|
Other transformation-related properties can be stacked to achieve combined transformation effects.
|
||||||
|
|
||||||
圆形裁剪变换示例
|
Example of circular cropping transformation:
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({ ImageKnifeOption:
|
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
|
||||||
{
|
{
|
||||||
loadSrc: $r('app.media.pngSample'),
|
loadSrc: $r('app.media.pngSample'),
|
||||||
objectFit: ImageFit.Cover,
|
objectFit: ImageFit.Cover,
|
||||||
border: { radius: 150 }
|
border: { radius: 150 }
|
||||||
}
|
})
|
||||||
}).width(300)
|
}).width(300)
|
||||||
.height(300)
|
.height(300)
|
||||||
```
|
```
|
||||||
|
|
||||||
圆形裁剪带边框变换示例
|
Example of Circular cropping with border transformation:
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({ ImageKnifeOption:
|
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
|
||||||
{
|
{
|
||||||
loadSrc: $r('app.media.pngSample'),
|
loadSrc: $r('app.media.pngSample'),
|
||||||
objectFit: ImageFit.Cover,
|
objectFit: ImageFit.Cover,
|
||||||
border: { radius: 150, color: Color.Red, width: 5 }
|
border: { radius: 150, color: Color.Red, width: 5 }
|
||||||
}
|
})
|
||||||
}).width(300)
|
}).width(300)
|
||||||
.height(300)
|
.height(300)
|
||||||
```
|
```
|
||||||
|
|
||||||
对比度滤波变换示例
|
Example of contrast filtering transformation:
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
imageKnifeOption: {
|
imageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc: $r('app.media.pngSample')
|
loadSrc: $r('app.media.pngSample')
|
||||||
}
|
})
|
||||||
}).width(300)
|
}).width(300)
|
||||||
.height(300)
|
.height(300)
|
||||||
.contrast(12)
|
.contrast(12)
|
||||||
```
|
```
|
||||||
|
|
||||||
旋转变换示例
|
Example of rotation transformation:
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
imageKnifeOption: {
|
imageKnifeOption: new ImageKnifeOption({
|
||||||
loadSrc: $r('app.media.pngSample')
|
loadSrc: $r('app.media.pngSample')
|
||||||
}
|
})
|
||||||
}).width(300)
|
}).width(300)
|
||||||
.height(300)
|
.height(300)
|
||||||
.rotate({angle:90})
|
.rotate({angle:90})
|
||||||
.backgroundColor(Color.Pink)
|
.backgroundColor(Color.Pink)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 8.监听图片加载成功与失败
|
#### 8. Listening for Image Loading Success and Failure
|
||||||
|
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({ ImageKnifeOption:
|
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
|
||||||
{
|
{
|
||||||
loadSrc: $r("app.media.rabbit"),
|
loadSrc: $r("app.media.rabbit"),
|
||||||
onLoadListener:{
|
onLoadListener:{
|
||||||
|
@ -242,128 +241,135 @@ ImageKnifeComponent({ ImageKnifeOption:
|
||||||
console.info(err)
|
console.info(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
```
|
```
|
||||||
#### 9.ImageKnifeComponent - syncLoad
|
#### 9. Use of syncLoad
|
||||||
设置是否同步加载图片,默认是异步加载。建议加载尺寸较小的本地图片时将syncLoad设为true,因为耗时较短,在主线程上执行即可
|
**syncLoad** sets whether to load the image synchronously. By default, the image is loaded asynchronously. When loading a small image, you are advised to set **syncLoad** to **true** so that the image loading can be quickly completed on the main thread.
|
||||||
```
|
```
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
imageKnifeOption:{
|
imageKnifeOption:new ImageKnifeOption({
|
||||||
loadSrc:$r("app.media.pngSample"),
|
loadSrc:$r("app.media.pngSample"),
|
||||||
placeholderSrc:$r("app.media.loading")
|
placeholderSrc:$r("app.media.loading")
|
||||||
},syncLoad:true
|
}),syncLoad:true
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
#### 10.ImageKnifeAnimatorComponent 示例
|
#### 10. Use of ImageKnifeAnimatorComponent
|
||||||
```
|
```
|
||||||
ImageKnifeAnimatorComponent({
|
ImageKnifeAnimatorComponent({
|
||||||
imageKnifeOption:{
|
imageKnifeOption:new ImageKnifeOption({
|
||||||
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
placeholderSrc:$r('app.media.loading'),
|
placeholderSrc:$r('app.media.loading'),
|
||||||
errorholderSrc:$r('app.media.failed')
|
errorholderSrc:$r('app.media.failed')
|
||||||
},animatorOption:this.animatorOption
|
}),animatorOption:this.animatorOption
|
||||||
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
|
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
|
||||||
```
|
```
|
||||||
## 接口说明
|
#### Reuse Scenario
|
||||||
### ImageKnife组件
|
Clear the component content in the **aboutToRecycle** lifecycle and trigger image loading through watch observeration.
|
||||||
| 组件名称 | 入参内容 | 功能简介 |
|
## Available APIs
|
||||||
|-----------------------------|---------------------------------|--------|
|
### ImageKnife
|
||||||
| ImageKnifeComponent | ImageKnifeOption | 图片显示组件 |
|
| Component | Parameter | Description |
|
||||||
| ImageKnifeAnimatorComponent | ImageKnifeOption、AnimatorOption | 动图控制组件 |
|
| --------------------------- | -------------------------------- | ------------ |
|
||||||
|
| ImageKnifeComponent | ImageKnifeOption | Image display component.|
|
||||||
|
| ImageKnifeAnimatorComponent | ImageKnifeOption, AnimatorOption| Animated image control component.|
|
||||||
|
|
||||||
### AnimatorOption参数列表
|
### AnimatorOption
|
||||||
| 参数名称 | 入参内容 | 功能简介 |
|
| Parameter | Type | Description |
|
||||||
|-----------------------|-------------------------------------------------------|----------|
|
| ---------- | --------------- | ---------------------------------------- |
|
||||||
| state | AnimationStatus | 播放状态(可选) |
|
| state | AnimationStatus | Playback status. Optional. |
|
||||||
| iterations | number | 播放次数(可选) |
|
| iterations | number | Number of playback times. Optional. |
|
||||||
| reverse | boolean | 播放顺序(可选) |
|
| reverse | boolean | Playback order. Optional. |
|
||||||
|
| onStart | ()=>void | Triggered when the animation starts. Optional. |
|
||||||
|
| onFinish | ()=>void | Triggered when the animation finishes or stops. Optional.|
|
||||||
|
| onPause | ()=>void | Triggered when the animation pauses. Optional. |
|
||||||
|
| onCancel | ()=>void | Triggered when the animation is canceled, that is, when it is reset to its initial state. Optional. |
|
||||||
|
| onRepeat | ()=>void | Triggered when the animation repeats. Optional. |
|
||||||
|
|
||||||
### ImageKnifeOption参数列表
|
### ImageKnifeOption
|
||||||
|
|
||||||
| 参数名称 | 入参内容 | 功能简介 |
|
| Parameter | Type | Description |
|
||||||
|-----------------------|-------------------------------------------------------|-----------------|
|
| --------------------- | ----------------------------------------------------- | ------------------------------ |
|
||||||
| loadSrc | string、PixelMap、Resource | 主图展示 |
|
| loadSrc | string, PixelMap, Resource | Main image. |
|
||||||
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
|
| placeholderSrc | PixelMap, Resource | Placeholder image. Optional. |
|
||||||
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
|
| errorholderSrc | PixelMap, Resource | Error image. Optional. |
|
||||||
| objectFit | ImageFit | 主图填充效果(可选) |
|
| objectFit | ImageFit | How the main image is resized to fit its container. Optional. |
|
||||||
| placeholderObjectFit | ImageFit | 占位图填充效果(可选) |
|
| placeholderObjectFit | ImageFit | How the placeholder image is resized to fit its container. Optional. |
|
||||||
| errorholderObjectFit | ImageFit | 错误图填充效果(可选) |
|
| errorholderObjectFit | ImageFit | How the error image is resized to fit its container. Optional. |
|
||||||
| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) |
|
| writeCacheStrategy | CacheStrategyType | Cache writing strategy. Optional. |
|
||||||
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
|
| onlyRetrieveFromCache | boolean | Whether to skip network and local requests. Optional.|
|
||||||
| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
|
| customGetImage | (context: Context, src: string | Custom image download. Optional. |
|
||||||
| border | BorderOptions | 边框圆角(可选) |
|
| border | BorderOptions | Border corner. Optional. |
|
||||||
| priority | taskpool.Priority | 加载优先级(可选) |
|
| priority | taskpool.Priority | Load priority. Optional. |
|
||||||
| context | common.UIAbilityContext | 上下文(可选) |
|
| context | common.UIAbilityContext | Context. Optional. |
|
||||||
| progressListener | (progress: number)=>void | 进度(可选) |
|
| progressListener | (progress: number)=>void | Progress. Optional. |
|
||||||
| signature | String | 自定义缓存关键字(可选) |
|
| signature | String | Custom cache signature. Optional. |
|
||||||
| headerOption | Array<HeaderOptions> | 设置请求头(可选) |
|
| headerOption | Array\<HeaderOptions> | Request headers. Optional. |
|
||||||
| transformation | PixelMapTransformation | 图片变换(可选) |
|
| transformation | PixelMapTransformation | Image transformation. Optional. |
|
||||||
| drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) |
|
| drawingColorFilter | ColorFilter | Drawing color filter. Optional. |
|
||||||
| onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) |
|
| onComplete | (event:EventImage \| undefined)=>void | Callback for image loading completion. Optional. |
|
||||||
| onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 |
|
| onLoadListener | onLoadStart:()=>void,onLoadSuccess:(data:string\|Pixelmap)=>void | Callback for image loading events. Optional. |
|
||||||
|
|
||||||
### ImageKnife接口
|
### ImageKnife
|
||||||
|
|
||||||
| 参数名称 | 入参内容 | 功能简介 |
|
| Parameter | Type | Description |
|
||||||
|------------------|-------------------------------------------------------------------------------------------------------|---------------|
|
| ----------------- | ------------------------------------------------------------ | -------------------------- |
|
||||||
| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 |
|
| initMemoryCache | newMemoryCache: IMemoryCache | Initializes a custom memory cache strategy. |
|
||||||
| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 |
|
| initFileCache | context: Context, size: number, memory: number | Initializes the file cache size and quantity |
|
||||||
| preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 |
|
| preLoadCache | loadSrc: string I ImageKnifeOption | Preloads and returns the file cache path. |
|
||||||
| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 |
|
| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | Obtains resources from memory or file cache.|
|
||||||
| addHeader | key: string, value: Object | 全局添加http请求头 |
|
| addHeader | key: string, value: Object | Adds a global HTTP request header. |
|
||||||
| setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 |
|
| setHeaderOptions | Array<HeaderOptions> | Sets global HTTP request headers. |
|
||||||
| deleteHeader | key: string | 全局删除http请求头 |
|
| deleteHeader | key: string | Deletes a global HTTP request header. |
|
||||||
| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined> | 全局设置自定义下载 |
|
| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap |
|
||||||
| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 |
|
| setEngineKeyImpl | IEngineKey | Sets a global cache key generation strategy. |
|
||||||
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 |
|
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | Writes to the memory disk cache. |
|
||||||
| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 |
|
| removeMemoryCache | url: string | Removes an entry from the memory cache. |
|
||||||
| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 |
|
| removeFileCache | url: string | Removes an entry from the file cache. |
|
||||||
### 图形变换类型(需要为GPUImage添加依赖项)
|
### Graphics tRansformation Types (GPUImage Dependency Required)
|
||||||
|
|
||||||
| 类型 | 相关描述 |
|
| Type | Description |
|
||||||
| ---------------------------------- | ----------------------------- |
|
| ------------------------ | ----------------------------- |
|
||||||
| BlurTransformation | 模糊处理 |
|
| BlurTransformation | Blurs the image. |
|
||||||
| BrightnessTransformation | 亮度滤波器 |
|
| BrightnessTransformation | Applies a brightness filter. |
|
||||||
| CropSquareTransformation | 正方形剪裁 |
|
| CropSquareTransformation | Crops the image to a square. |
|
||||||
| CropTransformation | 自定义矩形剪裁 |
|
| CropTransformation | Crops the image to a custom rectangle. |
|
||||||
| GrayScaleTransformation | 灰度级滤波器 |
|
| GrayScaleTransformation | Applies a grayscale filter. |
|
||||||
| InvertTransformation | 反转滤波器 |
|
| InvertTransformation | Applies an inversion filter. |
|
||||||
| KuwaharaTransformation | 桑原滤波器(使用GPUIImage) |
|
| KuwaharaTransformation | Applies a Kuwahara filter (requires **GPUImage**). |
|
||||||
| MaskTransformation | 遮罩 |
|
| MaskTransformation | Applies a mask. |
|
||||||
| PixelationTransformation | 像素化滤波器(使用GPUIImage) |
|
| PixelationTransformation | Applies a pixelation filter (requires **GPUImage**).|
|
||||||
| SepiaTransformation | 乌墨色滤波器(使用GPUIImage) |
|
| SepiaTransformation | Applies a sepia filter (requires **GPUImage**).|
|
||||||
| SketchTransformation | 素描滤波器(使用GPUIImage) |
|
| SketchTransformation | Applies a sketch filter (requires **GPUIImage**). |
|
||||||
| SwirlTransformation | 扭曲滤波器(使用GPUIImage) |
|
| SwirlTransformation | Applies a swirl filter (requires **GPUImage**). |
|
||||||
| ToonTransformation | 动画滤波器(使用GPUIImage) |
|
| ToonTransformation | Applies a cartoon filter (requires **GPUImage**). |
|
||||||
| VignetterTransformation | 装饰滤波器(使用GPUIImage) |
|
| VignetterTransformation | Applies a vignette filter (requires **GPUImage**). |
|
||||||
|
|
||||||
## 下载安装GPUImage依赖
|
## Downloading and Installing the GPUImage Dependency
|
||||||
方法一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。
|
Method 1: In the **Terminal** window, run the following command to install the third-party HAR. DevEco Studio will automatically add the HAR as a dependency to the **oh-package.json5** file of the project.
|
||||||
```
|
```
|
||||||
ohpm install @ohos/gpu_transform
|
ohpm install @ohos/gpu_transform
|
||||||
```
|
```
|
||||||
方法二: 在工程的oh-package.json5中设置三方包依赖,配置示例如下:
|
Method 2: Set the third-party HAR as a dependency in the **oh-package.json5** file of the project. The following is a configuration example:
|
||||||
```
|
```
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ohos/gpu_transform": "^1.0.2"
|
"@ohos/gpu_transform": "^1.0.2"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## 约束与限制
|
## Constraints
|
||||||
|
|
||||||
在下述版本验证通过:
|
This project has been verified in the following version:
|
||||||
DevEco Studio 5.0 Canary3(5.0.3.221)--SDK:API12
|
|
||||||
|
|
||||||
## 贡献代码
|
DevEco Studio: 5.0 Canary3 (5.0.3.502), SDK: API 12 (5.0.0.31)
|
||||||
|
|
||||||
使用过程中发现任何问题都可以提 [issue](https://gitee.com/openharmony-tpc/ImageKnife/issues)
|
## How to Contribute
|
||||||
给我们,当然,我们也非常欢迎你给我们发 [PR](https://gitee.com/openharmony-tpc/ImageKnife/issues) 。
|
|
||||||
|
|
||||||
## 开源协议
|
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.
|
||||||
|
|
||||||
本项目基于 [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE) ,请自由的享受和参与开源。
|
## License
|
||||||
|
|
||||||
## 遗留问题
|
This project is licensed under [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE).
|
||||||
|
|
||||||
- ImageKnifeAnimator组件无法设置ImageFit属性
|
## Known Issues
|
||||||
- ImageKnifeAnimator组件设置border属性无法将图片变为圆角
|
|
||||||
|
- The **ImageFit** attribute cannot be set for the **ImageKnifeAnimator** component.
|
||||||
|
- The **border** attribute of the **ImageKnifeAnimator** component cannot make the image rounded corners.
|
||||||
|
|
|
@ -0,0 +1,375 @@
|
||||||
|
# ImageKnife
|
||||||
|
|
||||||
|
**专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。**
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
本项目参考开源库 [Glide](https://github.com/bumptech/glide) 进行OpenHarmony的自研版本:
|
||||||
|
|
||||||
|
- 支持自定义内存缓存策略,支持设置内存缓存的大小(默认LRU策略)。
|
||||||
|
- 支持磁盘二级缓存,对于下载图片会保存一份至磁盘当中。
|
||||||
|
- 支持自定义实现图片获取/网络下载
|
||||||
|
- 支持监听网络下载回调进度
|
||||||
|
- 继承Image的能力,支持option传入border,设置边框,圆角
|
||||||
|
- 继承Image的能力,支持option传入objectFit设置图片缩放,包括objectFit为auto时根据图片自适应高度
|
||||||
|
- 支持通过设置transform缩放图片
|
||||||
|
- 并发请求数量,支持请求排队队列的优先级
|
||||||
|
- 支持生命周期已销毁的图片,不再发起请求
|
||||||
|
- 自定义缓存key
|
||||||
|
- 自定义http网络请求头
|
||||||
|
- 支持writeCacheStrategy控制缓存的存入策略(只存入内存或文件缓存)
|
||||||
|
- 支持preLoadCache预加载图片
|
||||||
|
- 支持onlyRetrieveFromCache仅用缓存加载
|
||||||
|
- 支持使用一个或多个图片变换,如模糊,高亮等
|
||||||
|
|
||||||
|
待实现特性
|
||||||
|
|
||||||
|
- 内存降采样优化,节约内存的占用
|
||||||
|
- 支持自定义图片解码
|
||||||
|
|
||||||
|
注意:3.x版本相对2.x版本做了重大的重构,主要体现在:
|
||||||
|
|
||||||
|
- 使用Image组件代替Canvas组件渲染
|
||||||
|
- 重构Dispatch分发逻辑,支持控制并发请求数,支持请求排队队列的优先级
|
||||||
|
- 支持通过initMemoryCache自定义策略内存缓存策略和大小
|
||||||
|
- 支持option自定义实现图片获取/网络下载
|
||||||
|
|
||||||
|
因此API及能力上,目前有部分差异,主要体现在:
|
||||||
|
|
||||||
|
- 不支持drawLifeCycle接口,通过canvas自会图片
|
||||||
|
- mainScaleType,border等参数,新版本与系统Image保持一致
|
||||||
|
- gif/webp动图播放与控制(ImageAnimator实现)
|
||||||
|
- 抗锯齿相关参数
|
||||||
|
|
||||||
|
## 下载安装
|
||||||
|
|
||||||
|
```
|
||||||
|
ohpm install @ohos/imageknife
|
||||||
|
|
||||||
|
// 如果需要用文件缓存,需要提前初始化文件缓存
|
||||||
|
await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
#### 1.显示本地资源图片
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc: $r("app.media.app_icon"),
|
||||||
|
placeholderSrc: $r("app.media.loading"),
|
||||||
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
|
objectFit: ImageFit.Auto
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.显示本地context files下文件
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc: this.localFile,
|
||||||
|
placeholderSrc: $r("app.media.loading"),
|
||||||
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
|
objectFit: ImageFit.Auto
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.显示网络图片
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
|
||||||
|
placeholderSrc: $r("app.media.loading"),
|
||||||
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
|
objectFit: ImageFit.Auto
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.自定义下载图片
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
|
||||||
|
placeholderSrc: $r("app.media.loading"),
|
||||||
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
|
objectFit: ImageFit.Auto,
|
||||||
|
customGetImage: custom
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
|
||||||
|
// 自定义实现图片获取方法,如自定义网络下载
|
||||||
|
@Concurrent
|
||||||
|
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> {
|
||||||
|
console.info("ImageKnife:: custom download:" + src)
|
||||||
|
// 举例写死从本地文件读取,也可以自己请求网络图片
|
||||||
|
return context.resourceManager.getMediaContentSync($r("app.media.bb").id).buffer as ArrayBuffer
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.监听网络下载进度
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
ImageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
|
||||||
|
progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)}
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.支持option传入border,设置边框,圆角
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
|
||||||
|
{
|
||||||
|
loadSrc: $r("app.media.rabbit"),
|
||||||
|
border: {radius:50}
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7.支持option图片变换
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
|
||||||
|
{
|
||||||
|
loadSrc: $r("app.media.rabbit"),
|
||||||
|
border: {radius:50},
|
||||||
|
transformation: new BlurTransformation(3)
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
多种组合变换用法
|
||||||
|
|
||||||
|
```
|
||||||
|
let transformations: collections.Array<PixelMapTransformation> = new collections.Array<PixelMapTransformation>();
|
||||||
|
transformations.push(new BlurTransformation(5));
|
||||||
|
transformations.push(new BrightnessTransformation(0.2));
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc: $r('app.media.pngSample'),
|
||||||
|
placeholderSrc: $r("app.media.loading"),
|
||||||
|
errorholderSrc: $r("app.media.app_icon"),
|
||||||
|
objectFit: ImageFit.Contain,
|
||||||
|
border: { radius: { topLeft: 50, bottomRight: 50 } }, // 圆角设置
|
||||||
|
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // 图形变换组
|
||||||
|
})
|
||||||
|
}).width(300)
|
||||||
|
.height(300)
|
||||||
|
.rotate({ angle: 90 }) // 旋转90度
|
||||||
|
.contrast(12) // 对比度滤波器
|
||||||
|
```
|
||||||
|
其它变换相关属性,可叠加实现组合变换效果
|
||||||
|
|
||||||
|
圆形裁剪变换示例
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
|
||||||
|
{
|
||||||
|
loadSrc: $r('app.media.pngSample'),
|
||||||
|
objectFit: ImageFit.Cover,
|
||||||
|
border: { radius: 150 }
|
||||||
|
})
|
||||||
|
}).width(300)
|
||||||
|
.height(300)
|
||||||
|
```
|
||||||
|
|
||||||
|
圆形裁剪带边框变换示例
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption(
|
||||||
|
{
|
||||||
|
loadSrc: $r('app.media.pngSample'),
|
||||||
|
objectFit: ImageFit.Cover,
|
||||||
|
border: { radius: 150, color: Color.Red, width: 5 }
|
||||||
|
})
|
||||||
|
}).width(300)
|
||||||
|
.height(300)
|
||||||
|
```
|
||||||
|
|
||||||
|
对比度滤波变换示例
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc: $r('app.media.pngSample')
|
||||||
|
})
|
||||||
|
}).width(300)
|
||||||
|
.height(300)
|
||||||
|
.contrast(12)
|
||||||
|
```
|
||||||
|
|
||||||
|
旋转变换示例
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: new ImageKnifeOption({
|
||||||
|
loadSrc: $r('app.media.pngSample')
|
||||||
|
})
|
||||||
|
}).width(300)
|
||||||
|
.height(300)
|
||||||
|
.rotate({angle:90})
|
||||||
|
.backgroundColor(Color.Pink)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8.监听图片加载成功与失败
|
||||||
|
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
|
||||||
|
{
|
||||||
|
loadSrc: $r("app.media.rabbit"),
|
||||||
|
onLoadListener:{
|
||||||
|
onLoadStart:()=>{
|
||||||
|
this.starTime = new Date().getTime()
|
||||||
|
console.info("Load start: ");
|
||||||
|
},
|
||||||
|
onLoadFailed: (err) => {
|
||||||
|
console.error("Load Failed Reason: " + err + " cost " + (new Date().getTime() - this.starTime) + " milliseconds");
|
||||||
|
},
|
||||||
|
onLoadSuccess: (data, imageData) => {
|
||||||
|
console.info("Load Successful: cost " + (new Date().getTime() - this.starTime) + " milliseconds");
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onLoadCancel(err){
|
||||||
|
console.info(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).width(100).height(100)
|
||||||
|
```
|
||||||
|
#### 9.ImageKnifeComponent - syncLoad
|
||||||
|
设置是否同步加载图片,默认是异步加载。建议加载尺寸较小的Resource图片时将syncLoad设为true,因为耗时较短,在主线程上执行即可
|
||||||
|
```
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption:new ImageKnifeOption({
|
||||||
|
loadSrc:$r("app.media.pngSample"),
|
||||||
|
placeholderSrc:$r("app.media.loading")
|
||||||
|
}),syncLoad:true
|
||||||
|
})
|
||||||
|
```
|
||||||
|
#### 10.ImageKnifeAnimatorComponent 示例
|
||||||
|
```
|
||||||
|
ImageKnifeAnimatorComponent({
|
||||||
|
imageKnifeOption:new ImageKnifeOption({
|
||||||
|
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
|
placeholderSrc:$r('app.media.loading'),
|
||||||
|
errorholderSrc:$r('app.media.failed')
|
||||||
|
}),animatorOption:this.animatorOption
|
||||||
|
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
|
||||||
|
```
|
||||||
|
#### 复用场景
|
||||||
|
在aboutToRecycle生命周期清空组件内容;通过watch监听触发图片的加载。
|
||||||
|
## 接口说明
|
||||||
|
### ImageKnife组件
|
||||||
|
| 组件名称 | 入参内容 | 功能简介 |
|
||||||
|
|-----------------------------|---------------------------------|--------|
|
||||||
|
| ImageKnifeComponent | ImageKnifeOption | 图片显示组件 |
|
||||||
|
| ImageKnifeAnimatorComponent | ImageKnifeOption、AnimatorOption | 动图控制组件 |
|
||||||
|
|
||||||
|
### AnimatorOption参数列表
|
||||||
|
| 参数名称 | 入参内容 | 功能简介 |
|
||||||
|
|------------|-----------------|----------|
|
||||||
|
| state | AnimationStatus | 播放状态(可选) |
|
||||||
|
| iterations | number | 播放次数(可选) |
|
||||||
|
| reverse | boolean | 播放顺序(可选) |
|
||||||
|
| onStart | ()=>void | 动画开始播放时触发(可选) |
|
||||||
|
| onFinish | ()=>void | 动画播放完成时或者停止播放时触发(可选) |
|
||||||
|
| onPause | ()=>void | 动画暂停播放时触发(可选) |
|
||||||
|
| onCancel | ()=>void | 动画返回最初状态时触发(可选) |
|
||||||
|
| onRepeat | ()=>void | 动画重复播放时触发(可选) |
|
||||||
|
|
||||||
|
### ImageKnifeOption参数列表
|
||||||
|
|
||||||
|
| 参数名称 | 入参内容 | 功能简介 |
|
||||||
|
|-----------------------|-------------------------------------------------------|-----------------|
|
||||||
|
| loadSrc | string、PixelMap、Resource | 主图展示 |
|
||||||
|
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
|
||||||
|
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
|
||||||
|
| objectFit | ImageFit | 主图填充效果(可选) |
|
||||||
|
| placeholderObjectFit | ImageFit | 占位图填充效果(可选) |
|
||||||
|
| errorholderObjectFit | ImageFit | 错误图填充效果(可选) |
|
||||||
|
| writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) |
|
||||||
|
| onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
|
||||||
|
| customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
|
||||||
|
| border | BorderOptions | 边框圆角(可选) |
|
||||||
|
| priority | taskpool.Priority | 加载优先级(可选) |
|
||||||
|
| context | common.UIAbilityContext | 上下文(可选) |
|
||||||
|
| progressListener | (progress: number)=>void | 进度(可选) |
|
||||||
|
| signature | String | 自定义缓存关键字(可选) |
|
||||||
|
| headerOption | Array<HeaderOptions> | 设置请求头(可选) |
|
||||||
|
| transformation | PixelMapTransformation | 图片变换(可选) |
|
||||||
|
| drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) |
|
||||||
|
| onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) |
|
||||||
|
| onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 |
|
||||||
|
|
||||||
|
### ImageKnife接口
|
||||||
|
|
||||||
|
| 参数名称 | 入参内容 | 功能简介 |
|
||||||
|
|------------------|-------------------------------------------------------------------------------------------------------|---------------|
|
||||||
|
| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 |
|
||||||
|
| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 |
|
||||||
|
| preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 |
|
||||||
|
| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 |
|
||||||
|
| addHeader | key: string, value: Object | 全局添加http请求头 |
|
||||||
|
| setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 |
|
||||||
|
| deleteHeader | key: string | 全局删除http请求头 |
|
||||||
|
| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined> | 全局设置自定义下载 |
|
||||||
|
| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 |
|
||||||
|
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 |
|
||||||
|
| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 |
|
||||||
|
| removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 |
|
||||||
|
### 图形变换类型(需要为GPUImage添加依赖项)
|
||||||
|
|
||||||
|
| 类型 | 相关描述 |
|
||||||
|
| ---------------------------------- | ----------------------------- |
|
||||||
|
| BlurTransformation | 模糊处理 |
|
||||||
|
| BrightnessTransformation | 亮度滤波器 |
|
||||||
|
| CropSquareTransformation | 正方形剪裁 |
|
||||||
|
| CropTransformation | 自定义矩形剪裁 |
|
||||||
|
| GrayScaleTransformation | 灰度级滤波器 |
|
||||||
|
| InvertTransformation | 反转滤波器 |
|
||||||
|
| KuwaharaTransformation | 桑原滤波器(使用GPUIImage) |
|
||||||
|
| MaskTransformation | 遮罩 |
|
||||||
|
| PixelationTransformation | 像素化滤波器(使用GPUIImage) |
|
||||||
|
| SepiaTransformation | 乌墨色滤波器(使用GPUIImage) |
|
||||||
|
| SketchTransformation | 素描滤波器(使用GPUIImage) |
|
||||||
|
| SwirlTransformation | 扭曲滤波器(使用GPUIImage) |
|
||||||
|
| ToonTransformation | 动画滤波器(使用GPUIImage) |
|
||||||
|
| VignetterTransformation | 装饰滤波器(使用GPUIImage) |
|
||||||
|
|
||||||
|
## 下载安装GPUImage依赖
|
||||||
|
方法一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。
|
||||||
|
```
|
||||||
|
ohpm install @ohos/gpu_transform
|
||||||
|
```
|
||||||
|
方法二: 在工程的oh-package.json5中设置三方包依赖,配置示例如下:
|
||||||
|
```
|
||||||
|
"dependencies": {
|
||||||
|
"@ohos/gpu_transform": "^1.0.2"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## 约束与限制
|
||||||
|
|
||||||
|
在下述版本验证通过:
|
||||||
|
DevEco Studio 5.0 Canary3(5.0.3.502)--SDK:API12 (5.0.0.31)
|
||||||
|
|
||||||
|
## 贡献代码
|
||||||
|
|
||||||
|
使用过程中发现任何问题都可以提 [issue](https://gitee.com/openharmony-tpc/ImageKnife/issues)
|
||||||
|
,当然,也非常欢迎发 [PR](https://gitee.com/openharmony-tpc/ImageKnife/pulls) 共建。
|
||||||
|
|
||||||
|
## 开源协议
|
||||||
|
|
||||||
|
本项目基于 [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE) ,请自由的享受和参与开源。
|
||||||
|
|
||||||
|
## 遗留问题
|
||||||
|
|
||||||
|
- ImageKnifeAnimator组件无法设置ImageFit属性
|
||||||
|
- ImageKnifeAnimator组件设置border属性无法将图片变为圆角
|
|
@ -17,7 +17,7 @@ import hilog from '@ohos.hilog';
|
||||||
import UIAbility from '@ohos.app.ability.UIAbility';
|
import UIAbility from '@ohos.app.ability.UIAbility';
|
||||||
import Want from '@ohos.app.ability.Want';
|
import Want from '@ohos.app.ability.Want';
|
||||||
import window from '@ohos.window';
|
import window from '@ohos.window';
|
||||||
import { ImageKnife, InitImageKnife, LogUtil } from '@ohos/libraryimageknife';
|
import { ImageKnife, InitImageKnife } from '@ohos/libraryimageknife';
|
||||||
import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl';
|
import { CustomEngineKeyImpl } from '../common/CustomEngineKeyImpl';
|
||||||
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
|
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
|
||||||
import { BusinessError } from '@ohos.base'
|
import { BusinessError } from '@ohos.base'
|
||||||
|
@ -47,7 +47,6 @@ export default class EntryAbility extends UIAbility {
|
||||||
|
|
||||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
||||||
|
|
||||||
LogUtil.mLogLevel = LogUtil.ALL
|
|
||||||
// 初始化ImageKnife的文件缓存
|
// 初始化ImageKnife的文件缓存
|
||||||
await InitImageKnife.init(this.context)
|
await InitImageKnife.init(this.context)
|
||||||
ImageKnife.getInstance().setEngineKeyImpl(new CustomEngineKeyImpl())
|
ImageKnife.getInstance().setEngineKeyImpl(new CustomEngineKeyImpl())
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
/*
|
||||||
|
* 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 { AnimatorOption, ImageKnifeAnimatorComponent } from "@ohos/libraryimageknife"
|
import { AnimatorOption, ImageKnifeAnimatorComponent } from "@ohos/libraryimageknife"
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
|
@ -5,7 +19,29 @@ import { AnimatorOption, ImageKnifeAnimatorComponent } from "@ohos/libraryimagek
|
||||||
struct ImageAnimatorPage {
|
struct ImageAnimatorPage {
|
||||||
@State animatorOption: AnimatorOption = {
|
@State animatorOption: AnimatorOption = {
|
||||||
state: AnimationStatus.Running,
|
state: AnimationStatus.Running,
|
||||||
iterations: -1
|
iterations: 1,
|
||||||
|
onFinish:()=>{
|
||||||
|
console.log("ImageKnifeAnimatorComponent animatorOption onFinish")
|
||||||
|
},
|
||||||
|
onStart:()=>{
|
||||||
|
console.log("ImageKnifeAnimatorComponent animatorOption onStart")
|
||||||
|
},
|
||||||
|
onPause:()=>{
|
||||||
|
console.log("ImageKnifeAnimatorComponent animatorOption onPause")
|
||||||
|
},
|
||||||
|
onCancel:()=>{
|
||||||
|
console.log("ImageKnifeAnimatorComponent animatorOption onCancel")
|
||||||
|
},
|
||||||
|
onRepeat:()=>{
|
||||||
|
console.log("ImageKnifeAnimatorComponent animatorOption onRepeat")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@State animatorOption1: AnimatorOption = {
|
||||||
|
state: AnimationStatus.Initial
|
||||||
|
}
|
||||||
|
@State animatorOption2: AnimatorOption = {
|
||||||
|
state: AnimationStatus.Initial,
|
||||||
|
reverse: true
|
||||||
}
|
}
|
||||||
build() {
|
build() {
|
||||||
Column(){
|
Column(){
|
||||||
|
@ -36,6 +72,22 @@ struct ImageAnimatorPage {
|
||||||
errorholderSrc:$r('app.media.failed')
|
errorholderSrc:$r('app.media.failed')
|
||||||
},animatorOption:this.animatorOption
|
},animatorOption:this.animatorOption
|
||||||
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
|
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
|
||||||
|
Text($r('app.string.Display_the_first_frame')).fontSize(20)
|
||||||
|
ImageKnifeAnimatorComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
|
placeholderSrc:$r('app.media.loading'),
|
||||||
|
errorholderSrc:$r('app.media.failed')
|
||||||
|
},animatorOption:this.animatorOption1
|
||||||
|
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
|
||||||
|
Text($r('app.string.Display_the_last_frame')).fontSize(20)
|
||||||
|
ImageKnifeAnimatorComponent({
|
||||||
|
imageKnifeOption:{
|
||||||
|
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
|
placeholderSrc:$r('app.media.loading'),
|
||||||
|
errorholderSrc:$r('app.media.failed')
|
||||||
|
},animatorOption:this.animatorOption2
|
||||||
|
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
|
||||||
}.width("100%").height("100%")
|
}.width("100%").height("100%")
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -78,7 +78,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('模糊效果').fontSize(20)
|
Text($r('app.string.Blur_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -91,7 +91,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('高亮效果').fontSize(20)
|
Text($r('app.string.Highlighting_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -104,7 +104,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('灰化效果').fontSize(20)
|
Text($r('app.string.Ashing_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -117,7 +117,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('反转效果').fontSize(20)
|
Text($r('app.string.Inverse_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -130,7 +130,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('动画滤镜效果').fontSize(20)
|
Text($r('app.string.Animation_filter_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -143,7 +143,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('裁剪圆形效果').fontSize(20)
|
Text($r('app.string.Crop_circular_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -156,7 +156,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('裁剪圆形带边框效果').fontSize(20)
|
Text($r('app.string.Crop_circular_with_border_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -168,7 +168,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('对比度效果').fontSize(20)
|
Text($r('app.string.Contrast_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -181,7 +181,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('乌墨色滤波效果').fontSize(20)
|
Text($r('app.string.Black_ink_filtering_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -193,7 +193,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('旋转效果').fontSize(20)
|
Text($r('app.string.Rotate')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -206,7 +206,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('圆角效果').fontSize(20)
|
Text($r('app.string.Corners')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -219,7 +219,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('桑原滤波效果').fontSize(20)
|
Text($r('app.string.Kuwahara_Filter_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -232,7 +232,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('像素化滤波效果').fontSize(20)
|
Text($r('app.string.Pixelated_Filter_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -245,7 +245,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('素描滤波效果').fontSize(20)
|
Text($r('app.string.Sketch_Filter_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -258,7 +258,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('扭曲滤波效果').fontSize(20)
|
Text($r('app.string.Distortion_Filter_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -271,7 +271,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('装饰滤波效果').fontSize(20)
|
Text($r('app.string.Decorative_Filter_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -284,7 +284,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('正方形裁剪效果').fontSize(20)
|
Text($r('app.string.Square_cutting_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -297,7 +297,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('上方裁剪效果').fontSize(20)
|
Text($r('app.string.Top_cutting_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -310,7 +310,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('中间裁剪效果').fontSize(20)
|
Text($r('app.string.Middle_cutting_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -323,7 +323,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('底下裁剪效果').fontSize(20)
|
Text($r('app.string.Bottom_cutting_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
|
||||||
|
@ -336,7 +336,7 @@ struct ImageTransformation {
|
||||||
})
|
})
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
Text('遮罩效果').fontSize(20)
|
Text($r('app.string.Mask_effect')).fontSize(20)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isContrast) {
|
if (this.isContrast) {
|
||||||
|
|
|
@ -18,6 +18,10 @@ import router from '@system.router';
|
||||||
@Component
|
@Component
|
||||||
struct Index {
|
struct Index {
|
||||||
|
|
||||||
|
getResourceString(res:Resource){
|
||||||
|
return getContext().resourceManager.getStringSync(res.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
|
|
||||||
|
@ -26,95 +30,100 @@ struct Index {
|
||||||
build() {
|
build() {
|
||||||
Scroll(){
|
Scroll(){
|
||||||
Column() {
|
Column() {
|
||||||
Button("测试ImageAnimator组件").onClick(()=>{
|
Button($r('app.string.Test_ImageAnimator')).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/ImageAnimatorPage',
|
uri: 'pages/ImageAnimatorPage',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("测试加载多张相同图片").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',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("测试HSP场景预加载").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_Task_error')).margin({top:10}).onClick(()=>{
|
||||||
|
router.push({
|
||||||
|
uri: 'pages/TestTaskResourcePage',
|
||||||
|
});
|
||||||
|
})
|
||||||
|
Button($r('app.string.Test_HSP')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestHspPreLoadImage',
|
uri: 'pages/TestHspPreLoadImage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("单个图片使用").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_SingleImage')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/SingleImage',
|
uri: 'pages/SingleImage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("全局自定义下载").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',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("多图 + LazyForEach").margin({top:10}).onClick(()=>{
|
Button(this.getResourceString($r('app.string.Multiple_images')) + " + LazyForEach").margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/ManyPhotoShowPage',
|
uri: 'pages/ManyPhotoShowPage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("多图 + reuse + LazyForeach").margin({top:10}).onClick(()=>{
|
Button(this.getResourceString($r('app.string.Multiple_images')) + " + reuse + LazyForeach").margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/UserPage',
|
uri: 'pages/UserPage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("长图显示").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Display_long_image')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/LongImagePage',
|
uri: 'pages/LongImagePage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("缩放图片").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Image_scaling')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TransformPage',
|
uri: 'pages/TransformPage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("消息+List").margin({top:10}).onClick(()=>{
|
Button(this.getResourceString($r('app.string.Message_list')) + " + List").margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestImageFlash',
|
uri: 'pages/TestImageFlash',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("自定义缓存key").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Custom_cache_key')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/SignatureTestPage',
|
uri: 'pages/SignatureTestPage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("预加载图片到文件缓存").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Preloading_images_to_cache')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestPrefetchToFileCache',
|
uri: 'pages/TestPrefetchToFileCache',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("从缓存获取图片显示").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Retrieve_image_display_from_cache')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestIsUrlExist',
|
uri: 'pages/TestIsUrlExist',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("测试单个请求头").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_single_request_header')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestHeader',
|
uri: 'pages/TestHeader',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("测试写入缓存策略").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_write_cache_strategy')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestWriteCacheStage',
|
uri: 'pages/TestWriteCacheStage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("图片变换").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Image_Transformation')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/ImageTransformation',
|
uri: 'pages/ImageTransformation',
|
||||||
|
|
||||||
|
@ -122,7 +131,7 @@ struct Index {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Button("不同的ObjectFit").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Different_ObjectFit')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/ObjectFitPage',
|
uri: 'pages/ObjectFitPage',
|
||||||
|
|
||||||
|
@ -130,24 +139,24 @@ struct Index {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Button('测试图片加载成功/失败事件').margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_image_loading_success_or_failure_events')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/LoadStatePage',
|
uri: 'pages/LoadStatePage',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Button('测试移除图片缓存接口').margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_removing_image_cache_interface')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestRemoveCache',
|
uri: 'pages/TestRemoveCache',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("测试错误图显示").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_error_image_display')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/TestErrorHolderPage',
|
uri: 'pages/TestErrorHolderPage',
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
Button("测试媒体url").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Test_media_URL')).margin({top:10}).onClick(()=>{
|
||||||
router.push({
|
router.push({
|
||||||
uri: 'pages/dataShareUriLoadPage',
|
uri: 'pages/dataShareUriLoadPage',
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,9 @@ struct SignatureTestPage {
|
||||||
Scroll() {
|
Scroll() {
|
||||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||||
|
|
||||||
Text("key固定为 1").fontSize(15)
|
Text($r('app.string.The_key_fixed_1')).fontSize(15)
|
||||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||||
Button("加载")
|
Button($r('app.string.Load'))
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
this.imageKnifeOption1 = {
|
this.imageKnifeOption1 = {
|
||||||
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
||||||
|
@ -46,9 +46,9 @@ struct SignatureTestPage {
|
||||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
||||||
}.width('100%').backgroundColor(Color.Pink)
|
}.width('100%').backgroundColor(Color.Pink)
|
||||||
|
|
||||||
Text("key每次变化:时间戳").fontSize(15)
|
Text($r('app.string.The_key_changes_timestamp')).fontSize(15)
|
||||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||||
Button("加载")
|
Button($r('app.string.Load'))
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
this.imageKnifeOption2 = {
|
this.imageKnifeOption2 = {
|
||||||
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
loadSrc: 'https://img-blog.csdn.net/20140514114029140',
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct SingleImage {
|
||||||
build() {
|
build() {
|
||||||
Scroll(this.scroller) {
|
Scroll(this.scroller) {
|
||||||
Column() {
|
Column() {
|
||||||
Text("本地资源svg图片")
|
Text($r('app.string.Local_SVG'))
|
||||||
.fontSize(30)
|
.fontSize(30)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
|
@ -56,7 +56,7 @@ struct SingleImage {
|
||||||
.onClick(()=>{
|
.onClick(()=>{
|
||||||
this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN);
|
this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN);
|
||||||
})
|
})
|
||||||
Text("本地context files下文件")
|
Text($r('app.string.Under_context_file'))
|
||||||
.fontSize(30)
|
.fontSize(30)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
|
@ -67,7 +67,7 @@ struct SingleImage {
|
||||||
objectFit: ImageFit.Contain
|
objectFit: ImageFit.Contain
|
||||||
}
|
}
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
Text("网络图片")
|
Text($r('app.string.Network_images'))
|
||||||
.fontSize(30)
|
.fontSize(30)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
|
@ -79,7 +79,7 @@ struct SingleImage {
|
||||||
progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)}
|
progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)}
|
||||||
}
|
}
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
Text("自定义下载")
|
Text($r('app.string.Custom_network_download'))
|
||||||
.fontSize(30)
|
.fontSize(30)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
|
@ -92,7 +92,7 @@ struct SingleImage {
|
||||||
transformation: new BlurTransformation(10)
|
transformation: new BlurTransformation(10)
|
||||||
}
|
}
|
||||||
}).width(100).height(100)
|
}).width(100).height(100)
|
||||||
Text("pixelMap加载图片")
|
Text($r('app.string.PixelMap_loads_images'))
|
||||||
.fontSize(30)
|
.fontSize(30)
|
||||||
.fontWeight(FontWeight.Bold)
|
.fontWeight(FontWeight.Bold)
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
|
|
|
@ -111,12 +111,12 @@ struct ImageTestPage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Row(){
|
Row(){
|
||||||
Text("点击尺寸加50")
|
Text($r('app.string.Click_on_add'))
|
||||||
.onClick(()=> {
|
.onClick(()=> {
|
||||||
this.imageSize = this.imageSize + 50
|
this.imageSize = this.imageSize + 50
|
||||||
})
|
})
|
||||||
.width('50%').backgroundColor(0x88ff0000).textAlign(TextAlign.Center).height(50)
|
.width('50%').backgroundColor(0x88ff0000).textAlign(TextAlign.Center).height(50)
|
||||||
Text("点击尺寸减50")
|
Text($r('app.string.Click_on_reduce'))
|
||||||
.onClick(()=> {
|
.onClick(()=> {
|
||||||
this.imageSize = Math.max(this.imageSize - 50, 0)
|
this.imageSize = Math.max(this.imageSize - 50, 0)
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,11 +28,11 @@ struct TestIsUrlExist {
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
Flex() {
|
Flex() {
|
||||||
Button("预加载gif图").onClick(() => {
|
Button($r('app.string.Preloading_GIF')).onClick(() => {
|
||||||
this.imageKnifeOption.loadSrc =
|
this.imageKnifeOption.loadSrc =
|
||||||
"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658"
|
"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658"
|
||||||
})
|
})
|
||||||
Button("内存缓存获取gif").onClick(() => {
|
Button($r('app.string.Retrieve_GIF_from_memory')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
CacheStrategy.Memory)
|
CacheStrategy.Memory)
|
||||||
|
@ -40,7 +40,7 @@ struct TestIsUrlExist {
|
||||||
this.source = data !== undefined ? data.source : $r("app.media.startIcon")
|
this.source = data !== undefined ? data.source : $r("app.media.startIcon")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Button("文件缓存获取gif").onClick(() => {
|
Button($r('app.string.Retrieve_GIF_from_disk')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
CacheStrategy.File)
|
CacheStrategy.File)
|
||||||
|
@ -51,11 +51,11 @@ struct TestIsUrlExist {
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex() {
|
Flex() {
|
||||||
Button("预加载静态图").onClick(() => {
|
Button($r('app.string.Preloading_static_images')).onClick(() => {
|
||||||
this.imageKnifeOption.loadSrc =
|
this.imageKnifeOption.loadSrc =
|
||||||
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp'
|
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp'
|
||||||
})
|
})
|
||||||
Button("内存缓存获取").onClick(() => {
|
Button($r('app.string.Retrieve_images_from_memory')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||||
CacheStrategy.Memory)
|
CacheStrategy.Memory)
|
||||||
|
@ -63,7 +63,7 @@ struct TestIsUrlExist {
|
||||||
this.source = data!.source
|
this.source = data!.source
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Button("文件缓存获取").onClick(() => {
|
Button($r('app.string.Retrieve_images_from_disk')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||||
CacheStrategy.File)
|
CacheStrategy.File)
|
||||||
|
|
|
@ -32,13 +32,13 @@ struct TestPrefetchToFileCachePage {
|
||||||
}
|
}
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
Button("url预加载图片到文件缓存").margin({top:10}).onClick(async ()=>{
|
Button($r('app.string.Preloading_images_to_file_cache_using_URL')).margin({top:10}).onClick(async ()=>{
|
||||||
await this.preload("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658")
|
await this.preload("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658")
|
||||||
})
|
})
|
||||||
Button("option预加载图片到文件缓存").margin({top:10}).onClick(async ()=>{
|
Button($r('app.string.Preloading_images_to_file_cache_using_option')).margin({top:10}).onClick(async ()=>{
|
||||||
await this.preload1("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658")
|
await this.preload1("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658")
|
||||||
})
|
})
|
||||||
Button("加载图片(预加载后可断网加载)").margin({top:10}).onClick(()=>{
|
Button($r('app.string.Load_image_offline_after_preloading')).margin({top:10}).onClick(()=>{
|
||||||
this.imageKnifeOption.loadSrc = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658"
|
this.imageKnifeOption.loadSrc = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658"
|
||||||
})
|
})
|
||||||
ImageKnifeComponent({
|
ImageKnifeComponent({
|
||||||
|
|
|
@ -29,12 +29,12 @@ struct TestRemoveCache {
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
Flex() {
|
Flex() {
|
||||||
Button("预加载gif图").onClick(() => {
|
Button($r('app.string.Preloading_GIF')).onClick(() => {
|
||||||
this.imageKnifeOption.loadSrc = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658";
|
this.imageKnifeOption.loadSrc = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658";
|
||||||
this.url = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658";
|
this.url = "https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658";
|
||||||
})
|
})
|
||||||
.margin({left:10})
|
.margin({left:10})
|
||||||
Button("内存缓存获取gif").onClick(() => {
|
Button($r('app.string.Retrieve_GIF_from_memory')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
CacheStrategy.Memory)
|
CacheStrategy.Memory)
|
||||||
|
@ -43,7 +43,7 @@ struct TestRemoveCache {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.margin({left:10})
|
.margin({left:10})
|
||||||
Button("文件缓存获取gif").onClick(() => {
|
Button($r('app.string.Retrieve_GIF_from_disk')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
.getCacheImage("https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
|
||||||
CacheStrategy.File)
|
CacheStrategy.File)
|
||||||
|
@ -55,12 +55,12 @@ struct TestRemoveCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex() {
|
Flex() {
|
||||||
Button("预加载静态图").onClick(() => {
|
Button($r('app.string.Preloading_static_images')).onClick(() => {
|
||||||
this.imageKnifeOption.loadSrc = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
this.imageKnifeOption.loadSrc = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
||||||
this.url = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
this.url = 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp';
|
||||||
})
|
})
|
||||||
.margin({left:10})
|
.margin({left:10})
|
||||||
Button("内存缓存获取").onClick(() => {
|
Button($r('app.string.Retrieve_images_from_memory')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||||
CacheStrategy.Memory)
|
CacheStrategy.Memory)
|
||||||
|
@ -69,7 +69,7 @@ struct TestRemoveCache {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.margin({left:10})
|
.margin({left:10})
|
||||||
Button("文件缓存获取").onClick(() => {
|
Button($r('app.string.Retrieve_images_from_disk')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
.getCacheImage('https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||||
CacheStrategy.File)
|
CacheStrategy.File)
|
||||||
|
@ -81,19 +81,19 @@ struct TestRemoveCache {
|
||||||
}.margin({ top: 10 })
|
}.margin({ top: 10 })
|
||||||
|
|
||||||
Flex() {
|
Flex() {
|
||||||
Button("删除全部缓存").onClick(() => {
|
Button($r('app.string.Delete_all_caches')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.removeAllMemoryCache()
|
.removeAllMemoryCache()
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.removeAllFileCache()
|
.removeAllFileCache()
|
||||||
})
|
})
|
||||||
.margin({left:5})
|
.margin({left:5})
|
||||||
Button("删除全部内存缓存").onClick(() => {
|
Button($r('app.string.Delete_all_memory_caches')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.removeAllMemoryCache()
|
.removeAllMemoryCache()
|
||||||
})
|
})
|
||||||
.margin({left:5})
|
.margin({left:5})
|
||||||
Button("删除全部文件缓存").onClick(() => {
|
Button($r('app.string.Delete_all_file_caches')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.removeAllFileCache()
|
.removeAllFileCache()
|
||||||
})
|
})
|
||||||
|
@ -101,12 +101,12 @@ struct TestRemoveCache {
|
||||||
}.margin({ top: 10 })
|
}.margin({ top: 10 })
|
||||||
|
|
||||||
Flex() {
|
Flex() {
|
||||||
Button("删除自定义内存缓存").onClick(() => {
|
Button($r('app.string.Delete_all_custom_memory_caches')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.removeMemoryCache(this.url)
|
.removeMemoryCache(this.url)
|
||||||
})
|
})
|
||||||
.margin({left:20})
|
.margin({left:20})
|
||||||
Button("删除自定义文件缓存").onClick(() => {
|
Button($r('app.string.Delete_all_custom_file_caches')).onClick(() => {
|
||||||
ImageKnife.getInstance()
|
ImageKnife.getInstance()
|
||||||
.removeFileCache(this.url)
|
.removeFileCache(this.url)
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
@ComponentV2
|
||||||
|
export struct ZuImage {
|
||||||
|
@Param @Require src: PixelMap | ResourceStr | string | undefined
|
||||||
|
@Param @Require placeholderSrc: PixelMap | ResourceStr | string | undefined
|
||||||
|
@Local errorholderSrc: PixelMap | ResourceStr | string | undefined
|
||||||
|
|
||||||
|
build() {
|
||||||
|
if (this.src) {
|
||||||
|
//当前版本存在bug
|
||||||
|
ImageKnifeComponent({
|
||||||
|
imageKnifeOption: {
|
||||||
|
loadSrc: this.src,
|
||||||
|
placeholderSrc: this.placeholderSrc,
|
||||||
|
errorholderSrc: this.errorholderSrc ?? this.placeholderSrc,
|
||||||
|
objectFit: ImageFit.Cover
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Image(this.placeholderSrc)
|
||||||
|
.objectFit(ImageFit.Cover)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@ComponentV2
|
||||||
|
struct TestTaskResourcePage {
|
||||||
|
@Local stateMenus: Array<string> = [
|
||||||
|
"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
|
||||||
|
'https://img-blog.csdnimg.cn/20191215043500229.png',
|
||||||
|
'https://img-blog.csdn.net/20140514114029140',
|
||||||
|
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
|
||||||
|
]
|
||||||
|
@Builder
|
||||||
|
_buildItem(item: string) {
|
||||||
|
Column({ space: 8 }) {
|
||||||
|
ZuImage({
|
||||||
|
src: item,
|
||||||
|
placeholderSrc: $r("app.media.loading")
|
||||||
|
}).width(44)
|
||||||
|
.height(44)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
|
||||||
|
Grid() {
|
||||||
|
ForEach(this.stateMenus, (item: string) => {
|
||||||
|
GridItem() {
|
||||||
|
this._buildItem(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}.width("100%")
|
||||||
|
.columnsTemplate('1fr 1fr 1fr 1fr 1fr')
|
||||||
|
.rowsGap(24)
|
||||||
|
.padding({
|
||||||
|
top: 24,
|
||||||
|
bottom: 24,
|
||||||
|
left: 24,
|
||||||
|
right: 24
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,12 +34,12 @@ struct TransformPage {
|
||||||
ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(200).width(200)
|
ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(200).width(200)
|
||||||
.transform(this.matrix1)
|
.transform(this.matrix1)
|
||||||
// Image($r('app.media.rabbit')).objectFit(ImageFit.Contain).height(200).width(200).transform(this.matrix1)
|
// Image($r('app.media.rabbit')).objectFit(ImageFit.Contain).height(200).width(200).transform(this.matrix1)
|
||||||
Button("放大").onClick(()=>{
|
Button($r('app.string.Enlarge')).onClick(()=>{
|
||||||
this.custom_scale = this.custom_scale * 2
|
this.custom_scale = this.custom_scale * 2
|
||||||
this.matrix1 = matrix4.identity().scale({ x: this.custom_scale, y: this.custom_scale })
|
this.matrix1 = matrix4.identity().scale({ x: this.custom_scale, y: this.custom_scale })
|
||||||
})
|
})
|
||||||
|
|
||||||
Button("缩小").onClick(()=>{
|
Button($r('app.string.Reduce')).onClick(()=>{
|
||||||
this.custom_scale = this.custom_scale / 2
|
this.custom_scale = this.custom_scale / 2
|
||||||
this.matrix1 = matrix4.identity().scale({ x: this.custom_scale, y: this.custom_scale })
|
this.matrix1 = matrix4.identity().scale({ x: this.custom_scale, y: this.custom_scale })
|
||||||
})
|
})
|
||||||
|
|
|
@ -32,9 +32,9 @@ struct DataShareUriLoadPage {
|
||||||
build() {
|
build() {
|
||||||
Scroll() {
|
Scroll() {
|
||||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||||
Text("获取媒体图库的uri用ImageKnife展示").fontSize(15)
|
Text($r('app.string.Retrieve_media_gallery')).fontSize(15)
|
||||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||||
Button("点击加载Uri并展示")
|
Button($r('app.string.Click_load_Uri'))
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
|
let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
|
||||||
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
|
photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
|
||||||
|
|
|
@ -19,6 +19,354 @@
|
||||||
{
|
{
|
||||||
"name": "app_permission_READ_IMAGEVIDEO",
|
"name": "app_permission_READ_IMAGEVIDEO",
|
||||||
"value": "获取读媒体资源权限"
|
"value": "获取读媒体资源权限"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_ImageAnimator",
|
||||||
|
"value": "Test ImageAnimator component"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_multiple_images",
|
||||||
|
"value": "Test loading multiple identical images"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_Task_error",
|
||||||
|
"value": "Test placeholder map Task error"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_HSP",
|
||||||
|
"value": "Test HSP scene preloading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_SingleImage",
|
||||||
|
"value": "SingleImage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_custom_download",
|
||||||
|
"value": "Global custom download"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Multiple_images",
|
||||||
|
"value": "Multiple images"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display_long_image",
|
||||||
|
"value": "Display long image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Image_scaling",
|
||||||
|
"value": "Image scaling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Message_list",
|
||||||
|
"value": "Message list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Custom_cache_key",
|
||||||
|
"value": "Custom cache key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_images_to_cache",
|
||||||
|
"value": "Preloading images to file cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_image_display_from_cache",
|
||||||
|
"value": "Retrieve image display from cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_single_request_header",
|
||||||
|
"value": "Test a single request header"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_write_cache_strategy",
|
||||||
|
"value": "Test write cache strategy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Image_Transformation",
|
||||||
|
"value": "Image Transformation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Different_ObjectFit",
|
||||||
|
"value": "Different ObjectFit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_image_loading_success_or_failure_events",
|
||||||
|
"value": "Test image loading success/failure events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_removing_image_cache_interface",
|
||||||
|
"value": "Test removing image cache interface"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_error_image_display",
|
||||||
|
"value": "Test error image display"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_media_URL",
|
||||||
|
"value": "Test media URL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display_the_first_frame",
|
||||||
|
"value": "Display the first frame of the animation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display_the_last_frame",
|
||||||
|
"value": "Display the last frame of the animation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Play",
|
||||||
|
"value": "Play"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pause",
|
||||||
|
"value": "Pause"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Stop",
|
||||||
|
"value": "Stop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Infinite_loop",
|
||||||
|
"value": "Infinite loop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Play_once",
|
||||||
|
"value": "Play once"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Play_twice",
|
||||||
|
"value": "Play twice"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Local_SVG",
|
||||||
|
"value": "Local SVG image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Under_context_file",
|
||||||
|
"value": "Files under context file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Network_images",
|
||||||
|
"value": "Network images"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Custom_network_download",
|
||||||
|
"value": "Custom network download"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PixelMap_loads_images",
|
||||||
|
"value": "PixelMap loads images"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Enlarge",
|
||||||
|
"value": "Enlarge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reduce",
|
||||||
|
"value": "Reduce"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Click_on_add",
|
||||||
|
"value": "Click on the size to add 50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Click_on_reduce",
|
||||||
|
"value": "Click to reduce size by 50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "The_key_fixed_1",
|
||||||
|
"value": "The key is fixed at 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "The_key_changes_timestamp",
|
||||||
|
"value": "Key changes every time: timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Load",
|
||||||
|
"value": "Load"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_images_to_file_cache_using_URL",
|
||||||
|
"value": "Preloading images to file cache using URL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_images_to_file_cache_using_option",
|
||||||
|
"value": "Preloading images to file cache using option"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Load_image_offline_after_preloading",
|
||||||
|
"value": "Load image (can be loaded offline after preloading)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_GIF",
|
||||||
|
"value": "Preloading GIF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_GIF_from_memory",
|
||||||
|
"value": "Retrieve GIF from memory cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_GIF_from_disk",
|
||||||
|
"value": "Retrieve GIF from disk cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_static_images",
|
||||||
|
"value": "Preloading static images"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_images_from_memory",
|
||||||
|
"value": "Retrieve images from memory cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_images_from_disk",
|
||||||
|
"value": "Retrieve images from memory disk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Write_memory_and_file",
|
||||||
|
"value": "Write to memory and file cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Write_memory",
|
||||||
|
"value": "Write to memory cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Write_file",
|
||||||
|
"value": "Write to file cache"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Main_image_Fill",
|
||||||
|
"value": "Main image Fill Stretch Fill"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Maintain_proportion_filling",
|
||||||
|
"value": "Maintain proportion filling in the placeholder map 'Include'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Error_graph_None",
|
||||||
|
"value": "Error graph None remains unchanged"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_failure_success",
|
||||||
|
"value": "Test failure/success"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Custom_download_failed",
|
||||||
|
"value": "Custom download failed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_media_gallery",
|
||||||
|
"value": "Retrieve the URI of the media gallery and display it using ImageKnife"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Click_load_Uri",
|
||||||
|
"value": "Click to load Uri and display"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_caches",
|
||||||
|
"value": "Delete all caches"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_memory_caches",
|
||||||
|
"value": "Delete all memory caches"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_file_caches",
|
||||||
|
"value": "Delete all file caches"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_custom_memory_caches",
|
||||||
|
"value": "Delete all custom memory caches"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_custom_file_caches",
|
||||||
|
"value": "Delete all custom file caches"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Blur_effect",
|
||||||
|
"value": "Blur effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Highlighting_effect",
|
||||||
|
"value": "Highlighting effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ashing_effect",
|
||||||
|
"value": "Ashing effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Inverse_effect",
|
||||||
|
"value": "Inverse effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Animation_filter_effect",
|
||||||
|
"value": "Animation filter effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Crop_circular_effect",
|
||||||
|
"value": "Crop circular effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Crop_circular_with_border_effect",
|
||||||
|
"value": "Crop circular with border effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Contrast_effect",
|
||||||
|
"value": "Contrast effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Black_ink_filtering_effect",
|
||||||
|
"value": "Black ink filtering effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rotate",
|
||||||
|
"value": "Rotate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Corners",
|
||||||
|
"value": "Corners"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kuwahara_Filter_effect",
|
||||||
|
"value": "Kuwahara filter effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pixelated_Filter_effect",
|
||||||
|
"value": "Pixelated filtering effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sketch_Filter_effect",
|
||||||
|
"value": "Sketch Filter effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Distortion_Filter_effect",
|
||||||
|
"value": "Distortion Filter effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Decorative_Filter_effect",
|
||||||
|
"value": "Decorative Filter effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Square_cutting_effect",
|
||||||
|
"value": "Square cutting effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Top_cutting_effect",
|
||||||
|
"value": "Top cutting effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Middle_cutting_effect",
|
||||||
|
"value": "Middle cutting effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bottom_cutting_effect",
|
||||||
|
"value": "Bottom cutting effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mask_effect",
|
||||||
|
"value": "Mask effect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TIPS",
|
||||||
|
"value": "Please shut down the network first and ensure that there is no cache of images from this network in the test failure scenario locally"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
Binary file not shown.
After Width: | Height: | Size: 922 KiB |
Binary file not shown.
|
@ -22,6 +22,7 @@
|
||||||
"pages/TestCommonImage",
|
"pages/TestCommonImage",
|
||||||
"pages/ImageAnimatorPage",
|
"pages/ImageAnimatorPage",
|
||||||
"pages/TestSetCustomImagePage",
|
"pages/TestSetCustomImagePage",
|
||||||
"pages/TestErrorHolderPage"
|
"pages/TestErrorHolderPage",
|
||||||
|
"pages/TestTaskResourcePage"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -19,6 +19,350 @@
|
||||||
{
|
{
|
||||||
"name": "app_permission_READ_IMAGEVIDEO",
|
"name": "app_permission_READ_IMAGEVIDEO",
|
||||||
"value": "获取读媒体资源权限"
|
"value": "获取读媒体资源权限"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_ImageAnimator",
|
||||||
|
"value": "测试ImageAnimator组件"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_multiple_images",
|
||||||
|
"value": "测试加载多张相同图片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_Task_error",
|
||||||
|
"value": "测试占位图Task报错"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_HSP",
|
||||||
|
"value": "测试HSP场景预加载"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_SingleImage",
|
||||||
|
"value": "单个图片使用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_custom_download",
|
||||||
|
"value": "全局自定义下载"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Multiple_images",
|
||||||
|
"value": "多图"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display_long_image",
|
||||||
|
"value": "长图显示"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Image_scaling",
|
||||||
|
"value": "缩放图片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Message_list",
|
||||||
|
"value": "消息列表"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Custom_cache_key",
|
||||||
|
"value": "自定义缓存key"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_images_to_cache",
|
||||||
|
"value": "预加载图片到文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_image_display_from_cache",
|
||||||
|
"value": "从缓存获取图片显示"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_single_request_header",
|
||||||
|
"value": "测试单个请求头"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_write_cache_strategy",
|
||||||
|
"value": "测试写入缓存策略"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Image_Transformation",
|
||||||
|
"value": "图片变换"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Different_ObjectFit",
|
||||||
|
"value": "不同的ObjectFit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_image_loading_success_or_failure_events",
|
||||||
|
"value": "测试图片加载成功/失败事件"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_removing_image_cache_interface",
|
||||||
|
"value": "测试移除图片缓存接口"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_error_image_display",
|
||||||
|
"value": "测试错误图显示"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display_the_first_frame",
|
||||||
|
"value": "动画显示第一帧"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display_the_last_frame",
|
||||||
|
"value": "动画显示最后一帧"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Play",
|
||||||
|
"value": "播放"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pause",
|
||||||
|
"value": "暂停"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Stop",
|
||||||
|
"value": "停止"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Infinite_loop",
|
||||||
|
"value": "无限循环"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Play_once",
|
||||||
|
"value": "播放一次"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Play_twice",
|
||||||
|
"value": "播放两次"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Local_SVG",
|
||||||
|
"value": "本地资源SVG图片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Under_context_file",
|
||||||
|
"value": "本地context files下文件"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Network_images",
|
||||||
|
"value": "网络图片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Custom_network_download",
|
||||||
|
"value": "自定义下载"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PixelMap_loads_images",
|
||||||
|
"value": "PixelMap加载图片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Enlarge",
|
||||||
|
"value": "放大"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reduce",
|
||||||
|
"value": "缩小"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Click_on_add",
|
||||||
|
"value": "点击尺寸加50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Click_on_reduce",
|
||||||
|
"value": "点击尺寸减50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "The_key_fixed_1",
|
||||||
|
"value": "key固定为 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "The_key_changes_timestamp",
|
||||||
|
"value": "key每次变化:时间戳"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Load",
|
||||||
|
"value": "加载"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_images_to_file_cache_using_URL",
|
||||||
|
"value": "url预加载图片到文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_images_to_file_cache_using_option",
|
||||||
|
"value": "option预加载图片到文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Load_image_offline_after_preloading",
|
||||||
|
"value": "加载图片(预加载后可断网加载)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_GIF",
|
||||||
|
"value": "预加载gif图"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_GIF_from_memory",
|
||||||
|
"value": "内存缓存获取gif"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_GIF_from_disk",
|
||||||
|
"value": "文件缓存获取gif"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Preloading_static_images",
|
||||||
|
"value": "预加载静态图"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_images_from_memory",
|
||||||
|
"value": "内存缓存获取"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_images_from_disk",
|
||||||
|
"value": "文件缓存获取"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Write_memory_and_file",
|
||||||
|
"value": "写入内存文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Write_memory",
|
||||||
|
"value": "写入内存缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Write_file",
|
||||||
|
"value": "写入文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Main_image_Fill",
|
||||||
|
"value": "主图Fill拉伸填充"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Maintain_proportion_filling",
|
||||||
|
"value": "占位图Contain保持比例填充"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Error_graph_None",
|
||||||
|
"value": "错误图None不变化"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Test_failure_success",
|
||||||
|
"value": "测试失败/成功场景"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Custom_download_failed",
|
||||||
|
"value": "自定义下载失败"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retrieve_media_gallery",
|
||||||
|
"value": "获取媒体图库的uri用ImageKnife展示"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Click_load_Uri",
|
||||||
|
"value": "点击加载Uri并展示"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_caches",
|
||||||
|
"value": "删除全部缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_memory_caches",
|
||||||
|
"value": "删除全部内存缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_file_caches",
|
||||||
|
"value": "删除全部文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_custom_memory_caches",
|
||||||
|
"value": "删除自定义内存缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Delete_all_custom_file_caches",
|
||||||
|
"value": "删除自定义文件缓存"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Blur_effect",
|
||||||
|
"value": "模糊效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Highlighting_effect",
|
||||||
|
"value": "高亮效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ashing_effect",
|
||||||
|
"value": "灰化效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Inverse_effect",
|
||||||
|
"value": "反转效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Animation_filter_effect",
|
||||||
|
"value": "动画滤镜效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Crop_circular_effect",
|
||||||
|
"value": "裁剪圆形效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Crop_circular_with_border_effect",
|
||||||
|
"value": "裁剪圆形带边框效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Contrast_effect",
|
||||||
|
"value": "对比度效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Black_ink_filtering_effect",
|
||||||
|
"value": "乌墨色滤波效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rotate",
|
||||||
|
"value": "旋转效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Corners",
|
||||||
|
"value": "圆角效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kuwahara_Filter_effect",
|
||||||
|
"value": "桑原滤波效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pixelated_Filter_effect",
|
||||||
|
"value": "像素化滤波效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sketch_Filter_effect",
|
||||||
|
"value": "素描滤波效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Distortion_Filter_effect",
|
||||||
|
"value": "扭曲滤波效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Decorative_Filter_effect",
|
||||||
|
"value": "装饰滤波效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Square_cutting_effect",
|
||||||
|
"value": "正方形裁剪效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Top_cutting_effect",
|
||||||
|
"value": "上方裁剪效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Middle_cutting_effect",
|
||||||
|
"value": "中间裁剪效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bottom_cutting_effect",
|
||||||
|
"value": "底下裁剪效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mask_effect",
|
||||||
|
"value": "遮罩效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TIPS",
|
||||||
|
"value": "测试失败场景请先关闭网络,并保证本地没有此网络图片的缓存"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -18,9 +18,9 @@ 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/ImageKnifeOption'
|
export { ImageKnifeOption , AnimatorOption } from './src/main/ets/model/ImageKnifeOption'
|
||||||
|
|
||||||
export { ImageKnifeRequest } from './src/main/ets/ImageKnifeRequest'
|
export { ImageKnifeRequest } from './src/main/ets/model/ImageKnifeRequest'
|
||||||
|
|
||||||
export { FileUtils } from './src/main/ets/utils/FileUtils'
|
export { FileUtils } from './src/main/ets/utils/FileUtils'
|
||||||
|
|
||||||
|
|
|
@ -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.0.2-rc.1",
|
"version": "3.0.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ohos/gpu_transform": "^1.0.2"
|
"@ohos/gpu_transform": "^1.0.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,14 +12,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeRequest } from './ImageKnifeRequest';
|
import { ImageKnifeRequest } from './model/ImageKnifeRequest';
|
||||||
import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData';
|
import { CacheStrategy, ImageKnifeData, ImageKnifeRequestSource } from './model/ImageKnifeData';
|
||||||
import { MemoryLruCache } from './utils/MemoryLruCache';
|
import { MemoryLruCache } from './cache/MemoryLruCache';
|
||||||
import { IMemoryCache } from './utils/IMemoryCache'
|
import { IMemoryCache } from './cache/IMemoryCache'
|
||||||
import { FileCache } from './utils/FileCache';
|
import { FileCache } from './cache/FileCache';
|
||||||
import { ImageKnifeDispatcher } from './ImageKnifeDispatcher';
|
import { ImageKnifeDispatcher } from './ImageKnifeDispatcher';
|
||||||
import { IEngineKey } from './key/IEngineKey';
|
import { IEngineKey } from './key/IEngineKey';
|
||||||
import { HeaderOptions, ImageKnifeOption } from './ImageKnifeOption';
|
import { HeaderOptions, ImageKnifeOption } from './model/ImageKnifeOption';
|
||||||
import { FileTypeUtil } from './utils/FileTypeUtil';
|
import { FileTypeUtil } from './utils/FileTypeUtil';
|
||||||
import { util } from '@kit.ArkTS';
|
import { util } from '@kit.ArkTS';
|
||||||
import { image } from '@kit.ImageKit';
|
import { image } from '@kit.ImageKit';
|
||||||
|
|
|
@ -12,24 +12,19 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeRequest, ImageKnifeRequestState } from './ImageKnifeRequest'
|
import { ImageKnifeRequest, ImageKnifeRequestState } from './model/ImageKnifeRequest'
|
||||||
import { DefaultJobQueue } from './utils/DefaultJobQueue'
|
import { DefaultJobQueue } from './queue/DefaultJobQueue'
|
||||||
import { IJobQueue } from './utils/IJobQueue'
|
import { IJobQueue } from './queue/IJobQueue'
|
||||||
import List from '@ohos.util.List';
|
import List from '@ohos.util.List';
|
||||||
import LightWeightMap from '@ohos.util.LightWeightMap';
|
import LightWeightMap from '@ohos.util.LightWeightMap';
|
||||||
import { LogUtil } from './utils/LogUtil';
|
import { LogUtil } from './utils/LogUtil';
|
||||||
import buffer from '@ohos.buffer';
|
|
||||||
import { FileCache } from './utils/FileCache';
|
|
||||||
import fs from '@ohos.file.fs';
|
|
||||||
import { ImageKnife } from './ImageKnife';
|
import { ImageKnife } from './ImageKnife';
|
||||||
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData';
|
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData';
|
||||||
import http from '@ohos.net.http';
|
|
||||||
import image from '@ohos.multimedia.image';
|
import image from '@ohos.multimedia.image';
|
||||||
import emitter from '@ohos.events.emitter';
|
import emitter from '@ohos.events.emitter';
|
||||||
import { Constants } from './utils/Constants';
|
import { Constants } from './utils/Constants';
|
||||||
import taskpool from '@ohos.taskpool';
|
import taskpool from '@ohos.taskpool';
|
||||||
import { FileTypeUtil } from './utils/FileTypeUtil';
|
import { FileTypeUtil } from './utils/FileTypeUtil';
|
||||||
import util from '@ohos.util';
|
|
||||||
import { IEngineKey } from './key/IEngineKey';
|
import { IEngineKey } from './key/IEngineKey';
|
||||||
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
||||||
import {
|
import {
|
||||||
|
@ -38,8 +33,9 @@ import {
|
||||||
RequestJobResult,
|
RequestJobResult,
|
||||||
RequestJobRequest
|
RequestJobRequest
|
||||||
} from './model/ImageKnifeData'
|
} from './model/ImageKnifeData'
|
||||||
import { combineArrayBuffers } from './model/utils';
|
|
||||||
import { BusinessError } from '@kit.BasicServicesKit';
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import { ImageKnifeLoader } from './ImageKnifeLoader'
|
||||||
|
|
||||||
|
|
||||||
export class ImageKnifeDispatcher {
|
export class ImageKnifeDispatcher {
|
||||||
// 最大并发
|
// 最大并发
|
||||||
|
@ -52,7 +48,7 @@ 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)
|
LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc + "requestSource=" + requestSource + " isAnimator=" + isAnimator)
|
||||||
let memoryCache: ImageKnifeData | undefined;
|
let memoryCache: ImageKnifeData | undefined;
|
||||||
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||||
memoryCache = {
|
memoryCache = {
|
||||||
|
@ -65,13 +61,12 @@ export class ImageKnifeDispatcher {
|
||||||
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
|
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (memoryCache !== undefined) {
|
if (memoryCache !== undefined) {
|
||||||
// 画主图
|
// 画主图
|
||||||
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||||
// 回调请求开始
|
// 回调请求开始
|
||||||
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
||||||
request.imageKnifeOption.onLoadListener?.onLoadStart()
|
request.imageKnifeOption.onLoadListener.onLoadStart()
|
||||||
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
|
||||||
|
@ -82,23 +77,22 @@ export class ImageKnifeDispatcher {
|
||||||
request.requestState = ImageKnifeRequestState.COMPLETE
|
request.requestState = ImageKnifeRequestState.COMPLETE
|
||||||
// 回调请求开结束
|
// 回调请求开结束
|
||||||
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
||||||
request.imageKnifeOption.onLoadListener?.onLoadSuccess(memoryCache.source,memoryCache)
|
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source,memoryCache)
|
||||||
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
||||||
request.requestState = ImageKnifeRequestState.ERROR
|
request.requestState = ImageKnifeRequestState.ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_true:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_hasmemory:" + request.imageKnifeOption.loadSrc)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_false:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_nomemory:" + request.imageKnifeOption.loadSrc)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
||||||
|
|
||||||
//1.内存有的话直接渲染
|
//1.内存有的话直接渲染
|
||||||
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
|
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
|
||||||
return
|
return
|
||||||
|
@ -157,10 +151,21 @@ export class ImageKnifeDispatcher {
|
||||||
isWatchProgress = true
|
isWatchProgress = true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
let src: string | number = ""
|
||||||
|
let moduleName: string = ""
|
||||||
|
let resName: string = ""
|
||||||
|
if((imageSrc as Resource).id != undefined) {
|
||||||
|
moduleName = (imageSrc as Resource).moduleName
|
||||||
|
src = (imageSrc as Resource).id
|
||||||
|
if(src == -1) {
|
||||||
|
resName = (imageSrc as Resource).params![0]
|
||||||
|
}
|
||||||
|
} else if(typeof imageSrc == "string") {
|
||||||
|
src = imageSrc
|
||||||
|
}
|
||||||
let request: RequestJobRequest = {
|
let request: RequestJobRequest = {
|
||||||
context: currentRequest.context,
|
context: currentRequest.context,
|
||||||
src: imageSrc,
|
src: src,
|
||||||
headers: currentRequest.imageKnifeOption.headerOption,
|
headers: currentRequest.imageKnifeOption.headerOption,
|
||||||
allHeaders: currentRequest.headers,
|
allHeaders: currentRequest.headers,
|
||||||
componentWidth:currentRequest.componentWidth,
|
componentWidth:currentRequest.componentWidth,
|
||||||
|
@ -176,7 +181,9 @@ export class ImageKnifeDispatcher {
|
||||||
isWatchProgress: isWatchProgress,
|
isWatchProgress: isWatchProgress,
|
||||||
memoryKey: memoryKey,
|
memoryKey: memoryKey,
|
||||||
fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(),
|
fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(),
|
||||||
isAnimator:isAnimator
|
isAnimator:isAnimator,
|
||||||
|
moduleName: moduleName == "" ? undefined : moduleName,
|
||||||
|
resName: resName == "" ? undefined : resName
|
||||||
}
|
}
|
||||||
|
|
||||||
if(request.customGetImage == undefined) {
|
if(request.customGetImage == undefined) {
|
||||||
|
@ -193,7 +200,7 @@ export class ImageKnifeDispatcher {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start:" + currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(subthread):" + currentRequest.imageKnifeOption.loadSrc)
|
||||||
taskpool.execute(task).then((res: Object) => {
|
taskpool.execute(task).then((res: Object) => {
|
||||||
this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
||||||
if (isWatchProgress){
|
if (isWatchProgress){
|
||||||
|
@ -202,7 +209,8 @@ export class ImageKnifeDispatcher {
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
LogUtil.error("Fail to execute 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)
|
||||||
}
|
}
|
||||||
|
@ -210,12 +218,14 @@ export class ImageKnifeDispatcher {
|
||||||
this.dispatchNextJob();
|
this.dispatchNextJob();
|
||||||
})
|
})
|
||||||
} else { //主线程请求
|
} else { //主线程请求
|
||||||
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):" + currentRequest.imageKnifeOption.loadSrc)
|
||||||
requestJob(request, requestList).then((res: RequestJobResult | undefined) => {
|
requestJob(request, requestList).then((res: RequestJobResult | undefined) => {
|
||||||
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
}).catch((err: BusinessError) => {
|
}).catch((err: BusinessError) => {
|
||||||
LogUtil.error("Fail to execute 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.executingJobMap.remove(memoryKey);
|
this.executingJobMap.remove(memoryKey);
|
||||||
this.dispatchNextJob();
|
this.dispatchNextJob();
|
||||||
})
|
})
|
||||||
|
@ -244,6 +254,7 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
let pixelmap = requestJobResult.pixelMap;
|
let pixelmap = requestJobResult.pixelMap;
|
||||||
if (pixelmap === undefined) {
|
if (pixelmap === undefined) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
// 回调请求失败
|
// 回调请求失败
|
||||||
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
||||||
|
@ -263,6 +274,7 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.executingJobMap.remove(memoryKey);
|
this.executingJobMap.remove(memoryKey);
|
||||||
|
this.dispatchNextJob();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 保存文件缓存
|
// 保存文件缓存
|
||||||
|
@ -297,8 +309,6 @@ export class ImageKnifeDispatcher {
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
if (requestList !== undefined) {
|
if (requestList !== undefined) {
|
||||||
|
|
||||||
// todo 判断request生命周期,已销毁的不需要再绘制
|
|
||||||
// key相同的request,一起绘制
|
// key相同的request,一起绘制
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
||||||
|
@ -346,11 +356,13 @@ export class ImageKnifeDispatcher {
|
||||||
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")
|
||||||
break // 队列已无任务
|
break // 队列已无任务
|
||||||
}
|
}
|
||||||
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.start executeJob:" + request.imageKnifeOption.loadSrc)
|
||||||
this.executeJob(request)
|
this.executeJob(request)
|
||||||
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc)
|
||||||
break
|
break
|
||||||
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
||||||
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed")
|
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed")
|
||||||
|
@ -381,292 +393,44 @@ export class ImageKnifeDispatcher {
|
||||||
*/
|
*/
|
||||||
@Concurrent
|
@Concurrent
|
||||||
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>): Promise<RequestJobResult | undefined> {
|
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>): Promise<RequestJobResult | undefined> {
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src)
|
LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src + " requestSource=" + request.requestSource)
|
||||||
let resBuf: ArrayBuffer | undefined
|
let src = typeof request.src == "number" ? request.resName != undefined ? request.resName : request.src + "" : request.src
|
||||||
let bufferSize: number = 0
|
// 生成文件缓存key
|
||||||
let loadError: string = '';
|
let fileKey = request.engineKey.generateFileKey(src, request.signature, request.isAnimator)
|
||||||
|
|
||||||
class RequestData {
|
//获取图片资源
|
||||||
receiveSize: number = 2000
|
let resBuf: ArrayBuffer
|
||||||
totalSize: number = 2000
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成文件key
|
|
||||||
let fileKey = request.engineKey.generateFileKey(request.src, request.signature,request.isAnimator)
|
|
||||||
|
|
||||||
// 判断自定义下载
|
|
||||||
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC) {
|
|
||||||
// 先从文件缓存获取
|
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
|
||||||
if (resBuf === undefined) {
|
|
||||||
LogUtil.log("customGetImage customGetImage");
|
|
||||||
resBuf = await request.customGetImage(request.context, request.src)
|
|
||||||
loadError = resBuf == undefined ? "customGetImage loadFile" : loadError
|
|
||||||
// 保存文件缓存
|
|
||||||
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
|
||||||
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug,不能直接获取resBuf.byteLength
|
|
||||||
bufferSize = copyBuf.byteLength
|
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (typeof request.src === 'string') {
|
|
||||||
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
|
|
||||||
// 先从文件缓存获取
|
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
|
||||||
if (resBuf === undefined && request.onlyRetrieveFromCache != true) {
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_httpRequest.start:"+request.src)
|
|
||||||
let httpRequest = http.createHttp();
|
|
||||||
let progress: number = 0
|
|
||||||
let arrayBuffers = new Array<ArrayBuffer>()
|
|
||||||
const headerObj: Record<string, object> = {}
|
|
||||||
if (request.headers != undefined) {
|
|
||||||
request.headers.forEach((value) => {
|
|
||||||
headerObj[value.key] = value.value
|
|
||||||
})
|
|
||||||
} else if (request.allHeaders.size > 0) {
|
|
||||||
request.allHeaders.forEach((value, key) => {
|
|
||||||
headerObj[key] = value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
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: 6000,
|
|
||||||
readTimeout: 6000,
|
|
||||||
// usingProtocol:http.HttpProtocol.HTTP1_1
|
|
||||||
// header: new Header('application/json')
|
|
||||||
});
|
|
||||||
|
|
||||||
await promise.then((data: number) => {
|
|
||||||
if (data == 200 || data == 204 || data == 201 || data == 206) {
|
|
||||||
resBuf = combineArrayBuffers(arrayBuffers)
|
|
||||||
} else {
|
|
||||||
loadError = "HttpDownloadClient has error, http code =" + JSON.stringify(data)
|
|
||||||
}
|
|
||||||
}).catch((err: Error) => {
|
|
||||||
loadError = err.message;
|
|
||||||
LogUtil.error("requestInStream ERROR : err = " + JSON.stringify(err));
|
|
||||||
});
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_httpRequest.end:"+request.src)
|
|
||||||
// 保存文件缓存
|
|
||||||
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
|
|
||||||
let copyBuf = combineArrayBuffers(arrayBuffers); // IDE有bug,不能直接获取resBuf.byteLength
|
|
||||||
bufferSize = copyBuf.byteLength
|
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogUtil.log("success get image from filecache for key = " + fileKey);
|
|
||||||
loadError = "success get image from filecache for key = " + fileKey;
|
|
||||||
}
|
|
||||||
} else if (request.src.startsWith('datashare://') || request.src.startsWith('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) => {
|
|
||||||
loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code;
|
|
||||||
})
|
|
||||||
}).catch((err:BusinessError) => {
|
|
||||||
loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code;
|
|
||||||
})
|
|
||||||
}).catch((err:BusinessError) => {
|
|
||||||
loadError ='LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code;
|
|
||||||
})
|
|
||||||
} else { //从本地文件获取
|
|
||||||
try {
|
try {
|
||||||
let stat = fs.statSync(request.src);
|
LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.start:" + request.src)
|
||||||
if (stat.size > 0) {
|
resBuf = await ImageKnifeLoader.getImageArrayBuffer(request, requestList, fileKey)
|
||||||
let file = fs.openSync(request.src, fs.OpenMode.READ_ONLY);
|
LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.end:" + request.src)
|
||||||
resBuf = new ArrayBuffer(stat.size);
|
} catch (error) {
|
||||||
fs.readSync(file.fd, resBuf);
|
LogUtil.error("ImageKnife_DataTime_requestJob.end: getImageArrayBuffer error " + request.src + " err=" + error)
|
||||||
fs.closeSync(file);
|
return ImageKnifeLoader.makeEmptyResult(error)
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (typeof err == 'string') {
|
|
||||||
loadError = err;
|
|
||||||
} else {
|
|
||||||
loadError = err.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((request.src as Resource).id !== undefined) { //从资源文件获取
|
|
||||||
let res = request.src as Resource;
|
|
||||||
let manager = request.context.createModuleContext(res.moduleName).resourceManager
|
|
||||||
if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) {
|
|
||||||
if(res.id == -1) {
|
|
||||||
let resName = (res.params![0] as string)
|
|
||||||
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
|
||||||
} else {
|
|
||||||
resBuf = manager.getMediaContentSync(res.id).buffer as ArrayBuffer
|
|
||||||
}
|
|
||||||
} else if (resBuf == undefined && request.requestSource != ImageKnifeRequestSource.SRC) {
|
|
||||||
if(res.id == -1) {
|
|
||||||
let resName = (res.params![0] as string)
|
|
||||||
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
|
||||||
} else {
|
|
||||||
resBuf = manager.getMediaContentSync(res.id).buffer as ArrayBuffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取图片类型
|
||||||
if (resBuf == undefined) {
|
let typeValue = new FileTypeUtil().getFileType(resBuf);
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.end_undefined:"+request.src)
|
|
||||||
return {
|
|
||||||
pixelMap: undefined,
|
|
||||||
bufferSize: 0,
|
|
||||||
fileKey: '',
|
|
||||||
loadFail: loadError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.start:"+request.src)
|
|
||||||
let fileTypeUtil = new FileTypeUtil();
|
|
||||||
let typeValue = fileTypeUtil.getFileType(resBuf);
|
|
||||||
if(typeValue == null) {
|
if(typeValue == null) {
|
||||||
return {
|
LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src)
|
||||||
pixelMap: undefined,
|
return ImageKnifeLoader.makeEmptyResult("request is not a valid image source")
|
||||||
bufferSize: 0,
|
|
||||||
fileKey: '',
|
|
||||||
loadFail: "request is not a valid image source",
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let imageSource: image.ImageSource = image.createImageSource(resBuf);
|
|
||||||
let decodingOptions: image.DecodingOptions = {
|
|
||||||
editable: true,
|
|
||||||
}
|
|
||||||
if(request.isAnimator) {
|
|
||||||
if (typeValue === 'gif' || typeValue === 'webp') {
|
|
||||||
let pixelMapList: Array<PixelMap> = []
|
|
||||||
let delayList: Array<number> = []
|
|
||||||
await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => {
|
|
||||||
//sdk的api接口发生变更:从.getDelayTime() 变为.getDelayTimeList()
|
|
||||||
await imageSource.getDelayTimeList().then(delayTimes => {
|
|
||||||
if (pixelList.length > 0) {
|
|
||||||
for (let i = 0; i < pixelList.length; i++) {
|
|
||||||
pixelMapList.push(pixelList[i]);
|
|
||||||
if (i < delayTimes.length) {
|
|
||||||
delayList.push(delayTimes[i]);
|
|
||||||
} else {
|
|
||||||
delayList.push(delayTimes[delayTimes.length - 1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imageSource.release();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
pixelMap: "",
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
type: typeValue,
|
|
||||||
pixelMapList,
|
|
||||||
delayList
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
pixelMap: undefined,
|
|
||||||
bufferSize: 0,
|
|
||||||
fileKey: '',
|
|
||||||
loadFail: "ImageKnifeAnimatorComponent组件仅支持动态图",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let resPixelmap: PixelMap | undefined = undefined
|
|
||||||
if (typeValue === 'gif' || typeValue === 'webp') {
|
|
||||||
let frameCount = await imageSource.getFrameCount()
|
|
||||||
let size = (await imageSource.getImageInfo()).size
|
|
||||||
if (frameCount == undefined || frameCount == 1) {
|
|
||||||
} else {
|
|
||||||
let base64Help = new util.Base64Helper()
|
|
||||||
|
|
||||||
let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(resBuf))
|
// 解析图片
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end_GIF:" + request.src)
|
LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.start:" + request.src)
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.end_GIF:" + request.src)
|
let result: RequestJobResult = await ImageKnifeLoader.parseImage(resBuf, typeValue, fileKey, request)
|
||||||
return {
|
LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.end:" + request.src)
|
||||||
pixelMap: base64str,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
size: size,
|
|
||||||
type: typeValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else if(typeValue == "svg") {
|
|
||||||
let hValue = Math.round(request.componentHeight);
|
|
||||||
let wValue = Math.round(request.componentWidth);
|
|
||||||
let defaultSize: image.Size = {
|
|
||||||
height: vp2px(hValue),
|
|
||||||
width: vp2px(wValue)
|
|
||||||
};
|
|
||||||
let opts: image.DecodingOptions = {
|
|
||||||
editable: true,
|
|
||||||
desiredSize: defaultSize
|
|
||||||
};
|
|
||||||
await imageSource.createPixelMap(opts)
|
|
||||||
.then((pixelmap: PixelMap) => {
|
|
||||||
resPixelmap = pixelmap
|
|
||||||
imageSource.release()
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
pixelMap: resPixelmap,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
type:typeValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let size = (await imageSource.getImageInfo()).size
|
|
||||||
await imageSource.createPixelMap(decodingOptions)
|
|
||||||
.then((pixelmap: PixelMap) => {
|
|
||||||
resPixelmap = pixelmap
|
|
||||||
imageSource.release()
|
|
||||||
})
|
|
||||||
|
|
||||||
// 图形变化
|
// 图形变化
|
||||||
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined) {
|
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && result?.pixelMap !== undefined && typeof result.pixelMap !== 'string') {
|
||||||
resPixelmap = await request.transformation?.transform(request.context, resPixelmap!, request.componentWidth, request.componentHeight);
|
LogUtil.log("ImageKnife_DataTime_requestJob.transform.start:" + request.src)
|
||||||
}
|
result.pixelMap = await request.transformation?.transform(request.context, result.pixelMap, request.componentWidth, request.componentHeight);
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end:"+request.src)
|
LogUtil.log("ImageKnife_DataTime_requestJob.transform.end:" + request.src)
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.end:"+request.src)
|
|
||||||
return {
|
|
||||||
pixelMap: resPixelmap,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
size:size,
|
|
||||||
type:typeValue
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob.end:" + request.src)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
CacheStrategy,
|
||||||
|
ImageKnifeRequestSource,
|
||||||
|
ImageKnifeRequestWithSource, RequestJobRequest } from './model/ImageKnifeData';
|
||||||
|
import List from '@ohos.util.List'
|
||||||
|
import { FileCache } from './cache/FileCache';
|
||||||
|
import { LogUtil } from './utils/LogUtil';
|
||||||
|
import { Constants } from './utils/Constants';
|
||||||
|
import http from '@ohos.net.http';
|
||||||
|
import { combineArrayBuffers } from './utils/ArrayBufferUtils';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import fs from '@ohos.file.fs';
|
||||||
|
import emitter from '@ohos.events.emitter';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
import { RequestJobResult } from './model/ImageKnifeData'
|
||||||
|
import util from '@ohos.util';
|
||||||
|
|
||||||
|
class RequestData {
|
||||||
|
receiveSize: number = 2000
|
||||||
|
totalSize: number = 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法,故抽取到另一个类
|
||||||
|
*/
|
||||||
|
export class ImageKnifeLoader {
|
||||||
|
static async parseImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
|
||||||
|
request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
if(request.isAnimator) {
|
||||||
|
return ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeValue === 'gif' || typeValue === 'webp') {
|
||||||
|
return ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request)
|
||||||
|
} else if(typeValue == "svg") {
|
||||||
|
return ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
static makeEmptyResult(error: string): RequestJobResult{
|
||||||
|
return {
|
||||||
|
pixelMap: undefined,
|
||||||
|
bufferSize: 0,
|
||||||
|
fileKey: '',
|
||||||
|
loadFail: error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest):Promise<RequestJobResult> {
|
||||||
|
let resPixelmap: PixelMap | undefined = undefined
|
||||||
|
let decodingOptions: image.DecodingOptions = {
|
||||||
|
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
|
||||||
|
}
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf)
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
|
await imageSource.createPixelMap(decodingOptions)
|
||||||
|
.then((pixelmap: PixelMap) => {
|
||||||
|
resPixelmap = pixelmap
|
||||||
|
imageSource.release()
|
||||||
|
}).catch((error: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
|
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
pixelMap: resPixelmap,
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
size:size,
|
||||||
|
type:typeValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
|
||||||
|
request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
let resPixelmap: PixelMap | undefined = undefined
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf)
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
|
let scale = size.height / size.width
|
||||||
|
let hValue = Math.round(request.componentHeight);
|
||||||
|
let wValue = Math.round(request.componentWidth);
|
||||||
|
let defaultSize: image.Size = {
|
||||||
|
height: vp2px(wValue) * scale,
|
||||||
|
width: vp2px(wValue)
|
||||||
|
};
|
||||||
|
let opts: image.DecodingOptions = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: defaultSize
|
||||||
|
};
|
||||||
|
await imageSource.createPixelMap(opts)
|
||||||
|
.then((pixelmap: PixelMap) => {
|
||||||
|
resPixelmap = pixelmap
|
||||||
|
imageSource.release()
|
||||||
|
}).catch((error: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
|
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
pixelMap: resPixelmap,
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
type:typeValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string,
|
||||||
|
fileKey: string,request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf)
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let frameCount = await imageSource.getFrameCount()
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
|
imageSource.release()
|
||||||
|
|
||||||
|
if(frameCount == undefined || frameCount == 1) {
|
||||||
|
} else {
|
||||||
|
let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf))
|
||||||
|
return {
|
||||||
|
pixelMap: base64str,
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
size:size,
|
||||||
|
type:typeValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request)
|
||||||
|
}
|
||||||
|
// 为AnimatorComponent解析动图
|
||||||
|
static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
if (typeValue === 'gif' || typeValue === 'webp') {
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf);
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
let decodingOptions: image.DecodingOptions = {
|
||||||
|
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
|
||||||
|
}
|
||||||
|
let pixelMapList: Array<PixelMap> = []
|
||||||
|
let delayList: Array<number> = []
|
||||||
|
await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => {
|
||||||
|
//sdk的api接口发生变更:从.getDelayTime() 变为.getDelayTimeList()
|
||||||
|
await imageSource.getDelayTimeList().then(delayTimes => {
|
||||||
|
if (pixelList.length > 0) {
|
||||||
|
for (let i = 0; i < pixelList.length; i++) {
|
||||||
|
pixelMapList.push(pixelList[i]);
|
||||||
|
if (i < delayTimes.length) {
|
||||||
|
delayList.push(delayTimes[i]);
|
||||||
|
} else {
|
||||||
|
delayList.push(delayTimes[delayTimes.length - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.release();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch((error: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
|
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error))
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
pixelMap: "",
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
type: typeValue,
|
||||||
|
pixelMapList,
|
||||||
|
delayList
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("ImageKnifeAnimatorComponent组件仅支持动态图")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取图片资源
|
||||||
|
static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string): Promise<ArrayBuffer> {
|
||||||
|
let resBuf: ArrayBuffer | undefined
|
||||||
|
|
||||||
|
// 判断自定义下载
|
||||||
|
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") {
|
||||||
|
// 先从文件缓存获取
|
||||||
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
||||||
|
if (resBuf === undefined) {
|
||||||
|
LogUtil.log("start customGetImage src=" + request.src)
|
||||||
|
try {
|
||||||
|
resBuf = await request.customGetImage(request.context, request.src)
|
||||||
|
LogUtil.log("end customGetImage src=" + request.src)
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error('customGetImage loadFile failed! err = ' + err)
|
||||||
|
}
|
||||||
|
if (resBuf === undefined) {
|
||||||
|
throw new Error('customGetImage loadFile failed!')
|
||||||
|
}
|
||||||
|
// 保存文件缓存
|
||||||
|
if (request.writeCacheStrategy !== CacheStrategy.Memory) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:" + request.src)
|
||||||
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf, request.fileCacheFolder)
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:" + request.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof request.src === 'string') {
|
||||||
|
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
|
||||||
|
// 先从文件缓存获取
|
||||||
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
||||||
|
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)
|
||||||
|
let httpRequest = http.createHttp();
|
||||||
|
let progress: number = 0
|
||||||
|
let arrayBuffers = new Array<ArrayBuffer>()
|
||||||
|
const headerObj: Record<string, object> = {}
|
||||||
|
if (request.headers != undefined) {
|
||||||
|
request.headers.forEach((value) => {
|
||||||
|
headerObj[value.key] = value.value
|
||||||
|
})
|
||||||
|
} else if (request.allHeaders.size > 0) {
|
||||||
|
request.allHeaders.forEach((value, key) => {
|
||||||
|
headerObj[key] = value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
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')
|
||||||
|
});
|
||||||
|
|
||||||
|
await promise.then((data: number) => {
|
||||||
|
if (data == 200 || data == 206 || data == 204) {
|
||||||
|
resBuf = combineArrayBuffers(arrayBuffers)
|
||||||
|
} else {
|
||||||
|
throw new Error("HttpDownloadClient has error, http code =" + JSON.stringify(data))
|
||||||
|
}
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
throw new Error("HttpDownloadClient download ERROR : err = " + JSON.stringify(err))
|
||||||
|
});
|
||||||
|
LogUtil.log("HttpDownloadClient.end:" + request.src)
|
||||||
|
// 保存文件缓存
|
||||||
|
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
|
||||||
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error('onlyRetrieveFromCache,do not fetch image src = ' + request.src)
|
||||||
|
}
|
||||||
|
} else if (request.src.startsWith('datashare://') || request.src.startsWith('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) => {
|
||||||
|
throw new Error('LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code)
|
||||||
|
})
|
||||||
|
}).catch((err:BusinessError) => {
|
||||||
|
throw new Error('LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code)
|
||||||
|
})
|
||||||
|
}).catch((err:BusinessError) => {
|
||||||
|
throw new Error('LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code)
|
||||||
|
})
|
||||||
|
} else { //从本地文件获取
|
||||||
|
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) {
|
||||||
|
throw new Error(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(10))).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(10))).buffer as ArrayBuffer
|
||||||
|
} else {
|
||||||
|
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resBuf === undefined){
|
||||||
|
throw new Error('getImageArrayBuffer undefined')
|
||||||
|
}
|
||||||
|
return resBuf
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,12 +13,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import util from '@ohos.util';
|
import util from '@ohos.util';
|
||||||
import { FileUtils } from './FileUtils';
|
import { FileUtils } from '../utils/FileUtils';
|
||||||
import fs from '@ohos.file.fs';
|
import fs from '@ohos.file.fs';
|
||||||
import { LogUtil } from './LogUtil';
|
import { LogUtil } from '../utils/LogUtil';
|
||||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
||||||
|
|
||||||
|
const INT_MAX = 2147483647
|
||||||
/**
|
/**
|
||||||
* 二级文件缓存
|
* 二级文件缓存
|
||||||
* 主线程通过lruCache管理缓存大小
|
* 主线程通过lruCache管理缓存大小
|
||||||
|
@ -34,12 +34,12 @@ export class FileCache {
|
||||||
private isInited: boolean = false
|
private isInited: boolean = false
|
||||||
private context?: Context
|
private context?: Context
|
||||||
readonly defaultMaxSize: number = 512;
|
readonly defaultMaxSize: number = 512;
|
||||||
readonly defaultSize: number = 128;
|
readonly defaultSize: number = INT_MAX;
|
||||||
readonly defaultMaxMemorySize: number = 512 * 1024 * 1024;
|
readonly defaultMaxMemorySize: number = 512 * 1024 * 1024;
|
||||||
readonly defaultMemorySize: number = 128 * 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) {
|
if (size <= 0 || size > INT_MAX) {
|
||||||
size = this.defaultSize
|
size = this.defaultSize
|
||||||
}
|
}
|
||||||
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
|
if (memory <= 0 || memory > this.defaultMaxMemorySize) {
|
||||||
|
@ -232,18 +232,18 @@ export class FileCache {
|
||||||
}
|
}
|
||||||
else if (value != undefined) {
|
else if (value != undefined) {
|
||||||
this.currentMemory -= value.byteLength
|
this.currentMemory -= value.byteLength
|
||||||
LogUtil.info("FileCache removeMemorySize: " + value.byteLength + " currentMemory:" + this.currentMemory)
|
LogUtil.debug("FileCache removeMemorySize: " + value.byteLength + " currentMemory:" + this.currentMemory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addMemorySize(value: ArrayBuffer | number): void {
|
private addMemorySize(value: ArrayBuffer | number): void {
|
||||||
if (typeof value == "number") {
|
if (typeof value == "number") {
|
||||||
this.currentMemory += value
|
this.currentMemory += value
|
||||||
LogUtil.info("FileCache addMemorySize: " + value + " currentMemory:" + this.currentMemory)
|
LogUtil.debug("FileCache addMemorySize: " + value + " currentMemory:" + this.currentMemory)
|
||||||
}
|
}
|
||||||
else if (value != undefined) {
|
else if (value != undefined) {
|
||||||
this.currentMemory += value.byteLength
|
this.currentMemory += value.byteLength
|
||||||
LogUtil.info("FileCache addMemorySize: " + value.byteLength + " currentMemory:" + this.currentMemory)
|
LogUtil.debug("FileCache addMemorySize: " + value.byteLength + " currentMemory:" + this.currentMemory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
* 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, ImageKnifeOption } from '../ImageKnifeOption';
|
import { AnimatorOption, ImageKnifeOption } from '../model/ImageKnifeOption';
|
||||||
import { ImageKnifeRequest, ImageKnifeRequestState } from '../ImageKnifeRequest';
|
import { ImageKnifeRequest, ImageKnifeRequestState } from '../model/ImageKnifeRequest';
|
||||||
import common from '@ohos.app.ability.common';
|
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';
|
||||||
|
@ -79,6 +79,11 @@ export struct ImageKnifeAnimatorComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.onStart(this.animatorOption.onStart)
|
||||||
|
.onFinish(this.animatorOption.onFinish)
|
||||||
|
.onPause(this.animatorOption.onPause)
|
||||||
|
.onCancel(this.animatorOption.onCancel)
|
||||||
|
.onRepeat(this.animatorOption.onRepeat)
|
||||||
}
|
}
|
||||||
|
|
||||||
watchImageKnifeOption() {
|
watchImageKnifeOption() {
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
* 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 { ImageKnifeOption } from '../ImageKnifeOption';
|
import { ImageKnifeOption } from '../model/ImageKnifeOption';
|
||||||
import { ImageKnifeRequest, ImageKnifeRequestState } from '../ImageKnifeRequest';
|
import { ImageKnifeRequest, ImageKnifeRequestState } from '../model/ImageKnifeRequest';
|
||||||
import common from '@ohos.app.ability.common';
|
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';
|
||||||
|
@ -38,43 +38,47 @@ export struct ImageKnifeComponent {
|
||||||
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
|
||||||
if(this.syncLoad) {
|
|
||||||
|
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()
|
||||||
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
|
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
|
||||||
if (memoryCacheSrc !== undefined){
|
if (memoryCacheSrc !== undefined){
|
||||||
LogUtil.log("aboutToAppear load from memory cache for key = "+ engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
|
LogUtil.log("aboutToAppear success load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc)
|
||||||
//画主图
|
|
||||||
this.pixelMap = memoryCacheSrc.source;
|
this.pixelMap = memoryCacheSrc.source;
|
||||||
}else{
|
}else{
|
||||||
|
LogUtil.log("aboutToAppear fail load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc)
|
||||||
|
if (this.imageKnifeOption.placeholderSrc !== undefined){
|
||||||
let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance()
|
let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance()
|
||||||
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption))
|
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption))
|
||||||
if (memoryCachePlace !== undefined){
|
if (memoryCachePlace !== undefined){
|
||||||
LogUtil.log("aboutToAppear load from memory cache for key = "+ engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
|
LogUtil.log("aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc)
|
||||||
//画主图
|
|
||||||
this.pixelMap = memoryCachePlace.source;
|
this.pixelMap = memoryCachePlace.source;
|
||||||
|
}else{
|
||||||
|
LogUtil.log("aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToDisappear(): void {
|
aboutToDisappear(): void {
|
||||||
if (this.request !== undefined) {
|
this.clearLastRequest()
|
||||||
this.request.requestState = ImageKnifeRequestState.DESTROY
|
|
||||||
this.request = undefined
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutToRecycle() {
|
aboutToRecycle() {
|
||||||
|
this.clearLastRequest()
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 对已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() {
|
||||||
Image(this.pixelMap)
|
Image(this.pixelMap)
|
||||||
.colorFilter(this.imageKnifeOption.drawingColorFilter)
|
.colorFilter(this.imageKnifeOption.drawingColorFilter)
|
||||||
|
@ -103,11 +107,13 @@ export struct ImageKnifeComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
watchImageKnifeOption() {
|
watchImageKnifeOption() {
|
||||||
if (this.request !== undefined) {
|
this.clearLastRequest()
|
||||||
this.request.requestState = ImageKnifeRequestState.DESTROY
|
|
||||||
}
|
|
||||||
this.request = undefined
|
|
||||||
this.componentVersion++
|
this.componentVersion++
|
||||||
|
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||||||
|
LogUtil.log("watchImageKnifeOption execute request:width=" + this.currentWidth + " height= " + this.currentHeight
|
||||||
|
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc
|
||||||
|
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc
|
||||||
|
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc)
|
||||||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5';
|
||||||
import { ImageKnifeOption } from '../ImageKnifeOption';
|
import { ImageKnifeOption } from '../model/ImageKnifeOption';
|
||||||
import { IEngineKey } from './IEngineKey';
|
import { IEngineKey } from './IEngineKey';
|
||||||
import { PixelMapTransformation } from '../transform/PixelMapTransformation';
|
import { PixelMapTransformation } from '../transform/PixelMapTransformation';
|
||||||
import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
|
import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeOption } from '../ImageKnifeOption'
|
import { ImageKnifeOption } from '../model/ImageKnifeOption'
|
||||||
import { ImageKnifeRequestSource } from '../model/ImageKnifeData'
|
import { ImageKnifeRequestSource } from '../model/ImageKnifeData'
|
||||||
|
|
||||||
export interface IEngineKey {
|
export interface IEngineKey {
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
* 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 { HeaderOptions } from '../ImageKnifeOption'
|
import { HeaderOptions } from './ImageKnifeOption'
|
||||||
import { ImageKnifeRequest } from '../ImageKnifeRequest'
|
import { ImageKnifeRequest } from './ImageKnifeRequest'
|
||||||
import { IEngineKey } from '../key/IEngineKey'
|
import { IEngineKey } from '../key/IEngineKey'
|
||||||
import { PixelMapTransformation } from '../transform/PixelMapTransformation'
|
import { PixelMapTransformation } from '../transform/PixelMapTransformation'
|
||||||
import common from '@ohos.app.ability.common';
|
import common from '@ohos.app.ability.common';
|
||||||
|
@ -86,7 +86,7 @@ export interface RequestJobResult {
|
||||||
*/
|
*/
|
||||||
export interface RequestJobRequest {
|
export interface RequestJobRequest {
|
||||||
context: common.UIAbilityContext,
|
context: common.UIAbilityContext,
|
||||||
src: string | PixelMap | Resource,
|
src: string | number,
|
||||||
headers?: Array<HeaderOptions>,
|
headers?: Array<HeaderOptions>,
|
||||||
allHeaders: Map<string, Object>,
|
allHeaders: Map<string, Object>,
|
||||||
componentWidth: number,
|
componentWidth: number,
|
||||||
|
@ -101,6 +101,8 @@ export interface RequestJobRequest {
|
||||||
isWatchProgress: boolean
|
isWatchProgress: boolean
|
||||||
memoryKey: string
|
memoryKey: string
|
||||||
fileCacheFolder: string,
|
fileCacheFolder: string,
|
||||||
isAnimator?: boolean
|
isAnimator?: boolean,
|
||||||
|
moduleName?:string,
|
||||||
|
resName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
*/
|
*/
|
||||||
import taskpool from '@ohos.taskpool';
|
import taskpool from '@ohos.taskpool';
|
||||||
import common from '@ohos.app.ability.common'
|
import common from '@ohos.app.ability.common'
|
||||||
import { CacheStrategy, ImageKnifeData,EventImage } from './model/ImageKnifeData';
|
import { CacheStrategy, ImageKnifeData,EventImage } from './ImageKnifeData';
|
||||||
import { PixelMapTransformation } from './transform/PixelMapTransformation';
|
import { PixelMapTransformation } from '../transform/PixelMapTransformation';
|
||||||
import { drawing } from '@kit.ArkGraphics2D';
|
import { drawing } from '@kit.ArkGraphics2D';
|
||||||
|
|
||||||
export interface HeaderOptions {
|
export interface HeaderOptions {
|
||||||
|
@ -31,6 +31,16 @@ export class AnimatorOption {
|
||||||
iterations?: number = -1
|
iterations?: number = -1
|
||||||
@Track
|
@Track
|
||||||
reverse?: boolean = false
|
reverse?: boolean = false
|
||||||
|
@Track
|
||||||
|
onStart?:()=>void
|
||||||
|
@Track
|
||||||
|
onFinish?:()=>void
|
||||||
|
@Track
|
||||||
|
onPause?:()=>void
|
||||||
|
@Track
|
||||||
|
onCancel?:()=>void
|
||||||
|
@Track
|
||||||
|
onRepeat?:()=>void
|
||||||
}
|
}
|
||||||
|
|
||||||
@Observed
|
@Observed
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeOption } from './ImageKnifeOption';
|
import { ImageKnifeOption } from './ImageKnifeOption';
|
||||||
import common from '@ohos.app.ability.common';
|
import common from '@ohos.app.ability.common';
|
||||||
import { ImageKnifeRequestSource } from './model/ImageKnifeData';
|
import { ImageKnifeRequestSource } from './ImageKnifeData';
|
||||||
|
|
||||||
|
|
||||||
export class ImageKnifeRequest {
|
export class ImageKnifeRequest {
|
|
@ -12,7 +12,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeRequest } from '../ImageKnifeRequest';
|
import { ImageKnifeRequest } from '../model/ImageKnifeRequest';
|
||||||
import { IJobQueue } from './IJobQueue'
|
import { IJobQueue } from './IJobQueue'
|
||||||
import Queue from '@ohos.util.Queue';
|
import Queue from '@ohos.util.Queue';
|
||||||
import { taskpool,Stack } from '@kit.ArkTS';
|
import { taskpool,Stack } from '@kit.ArkTS';
|
|
@ -12,7 +12,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { ImageKnifeRequest } from '../ImageKnifeRequest'
|
import { ImageKnifeRequest } from '../model/ImageKnifeRequest'
|
||||||
|
|
||||||
export interface IJobQueue {
|
export interface IJobQueue {
|
||||||
|
|
|
@ -12,44 +12,29 @@
|
||||||
* 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 { hilog } from '@kit.PerformanceAnalysisKit';
|
||||||
|
|
||||||
export class LogUtil {
|
export class LogUtil {
|
||||||
public static OFF: number = 1
|
public static readonly DOMAIN: number = 0xD002220;
|
||||||
public static LOG: number = 2
|
public static readonly TAG: string = "ImageKnife::";
|
||||||
public static DEBUG: number = 3
|
|
||||||
public static INFO: number = 4
|
|
||||||
public static WARN: number = 5
|
|
||||||
public static ERROR: number = 6
|
|
||||||
public static ALL: number = 7
|
|
||||||
public static mLogLevel: number = LogUtil.OFF;
|
|
||||||
public static TAG: string = "ImageKnife:: ";
|
|
||||||
|
|
||||||
public static debug(message: string, ...args: Object[]) {
|
public static debug(message: string, ...args: Object[]) {
|
||||||
if (LogUtil.mLogLevel >= LogUtil.DEBUG) {
|
hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
console.debug(LogUtil.TAG + message, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static info(message: string, ...args: Object[]) {
|
public static info(message: string, ...args: Object[]) {
|
||||||
if (LogUtil.mLogLevel >= LogUtil.INFO) {
|
hilog.info(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
console.info(LogUtil.TAG + message, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static log(message: string, ...args: Object[]) {
|
public static log(message: string, ...args: Object[]) {
|
||||||
if (LogUtil.mLogLevel >= LogUtil.LOG) {
|
hilog.debug(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
console.log(LogUtil.TAG + message, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static warn(message: string, ...args: Object[]) {
|
public static warn(message: string, ...args: Object[]) {
|
||||||
if (LogUtil.mLogLevel >= LogUtil.WARN) {
|
hilog.warn(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
console.warn(LogUtil.TAG + message, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static error(message: string, ...args: Object[]) {
|
public static error(message: string, ...args: Object[]) {
|
||||||
if (LogUtil.mLogLevel >= LogUtil.ERROR) {
|
hilog.error(LogUtil.DOMAIN, LogUtil.TAG, message, args)
|
||||||
console.error(LogUtil.TAG + message, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'
|
|
||||||
import util from '@ohos.util'
|
|
||||||
|
|
||||||
export class Tools {
|
|
||||||
private static keyCache: util.LRUCache<string,string> = new util.LRUCache(1024)
|
|
||||||
public static generateMemoryKey(key: string | PixelMap | Resource): string{
|
|
||||||
return typeof key == "string"? key : JSON.stringify(key)
|
|
||||||
}
|
|
||||||
// 生成唯一的key
|
|
||||||
public static generateKey(key: string | PixelMap | Resource): string{
|
|
||||||
let keyCache = typeof key == "string"? key : JSON.stringify(key)
|
|
||||||
let result = Tools.keyCache.get(keyCache)
|
|
||||||
if(result != undefined) {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result = SparkMD5.hashBinary(keyCache)
|
|
||||||
Tools.keyCache.put(keyCache,result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue