更新说明:
- 支持hsp多包图片资源 - 新增putCache写入缓存接口 - 修复入参为pixelMap图片不显示问题 Signed-off-by: 明月清风 <qiufeihu1@h-partners.com>
This commit is contained in:
parent
dd24720c00
commit
7030f5f55a
|
@ -1,4 +1,9 @@
|
|||
|
||||
## 3.0.0-rc.4
|
||||
- 支持hsp多包图片资源
|
||||
- 新增putCache写入缓存接口
|
||||
- 修复入参为pixelMap图片不显示问题
|
||||
|
||||
## 3.0.0-rc.3
|
||||
- 将请求默认并行从64调整到8,减少对taskpool execute内存消耗
|
||||
- 补充option参数:placeholderObjectFit,errorholderObjectFit分别支持占位图填充效果和错误图填充效果
|
||||
|
|
29
README.md
29
README.md
|
@ -23,23 +23,27 @@
|
|||
- 支持使用一个或多个图片变换,如模糊,高亮等
|
||||
|
||||
待实现特性
|
||||
|
||||
- gif/webp动图显示与控制
|
||||
- 内存降采样优化,节约内存的占用
|
||||
- 支持自定义图片解码
|
||||
|
||||
注意:3.x版本相对2.x版本做了重大的重构,主要体现在:
|
||||
|
||||
- 使用Image组件代替Canvas组件渲染
|
||||
- 重构Dispatch分发逻辑,支持控制并发请求数,支持请求排队队列的优先级
|
||||
- 支持通过initMemoryCache自定义策略内存缓存策略和大小
|
||||
- 支持option自定义实现图片获取/网络下载
|
||||
|
||||
因此API及能力上,目前有部分差异,主要体现在:
|
||||
|
||||
- 不支持drawLifeCycle接口,通过canvas自会图片
|
||||
- mainScaleType,border等参数,新版本与系统Image保持一致
|
||||
- gif/webp动图播放与控制
|
||||
- 抗锯齿相关参数
|
||||
|
||||
## 下载安装
|
||||
|
||||
```
|
||||
ohpm install @ohos/imageknife
|
||||
|
||||
|
@ -48,7 +52,9 @@ await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
|
|||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
#### 1.显示本地资源图片
|
||||
|
||||
```
|
||||
ImageKnifeComponent({
|
||||
ImageKnifeOption: {
|
||||
|
@ -61,6 +67,7 @@ ImageKnifeComponent({
|
|||
```
|
||||
|
||||
#### 2.显示本地context files下文件
|
||||
|
||||
```
|
||||
ImageKnifeComponent({
|
||||
ImageKnifeOption: {
|
||||
|
@ -73,6 +80,7 @@ ImageKnifeComponent({
|
|||
```
|
||||
|
||||
#### 3.显示网络图片
|
||||
|
||||
```
|
||||
ImageKnifeComponent({
|
||||
ImageKnifeOption: {
|
||||
|
@ -85,6 +93,7 @@ ImageKnifeComponent({
|
|||
```
|
||||
|
||||
#### 4.自定义下载图片
|
||||
|
||||
```
|
||||
ImageKnifeComponent({
|
||||
ImageKnifeOption: {
|
||||
|
@ -106,6 +115,7 @@ async function custom(context: Context, src: string | PixelMap | Resource): Prom
|
|||
```
|
||||
|
||||
#### 5.监听网络下载进度
|
||||
|
||||
```
|
||||
ImageKnifeComponent({
|
||||
ImageKnifeOption: {
|
||||
|
@ -114,7 +124,9 @@ ImageKnifeComponent({
|
|||
}
|
||||
}).width(100).height(100)
|
||||
```
|
||||
|
||||
#### 6.支持option传入border,设置边框,圆角
|
||||
|
||||
```
|
||||
ImageKnifeComponent({ ImageKnifeOption:
|
||||
{
|
||||
|
@ -123,7 +135,9 @@ ImageKnifeComponent({ ImageKnifeOption:
|
|||
}
|
||||
}).width(100).height(100)
|
||||
```
|
||||
|
||||
#### 7.支持option图片变换
|
||||
|
||||
```
|
||||
ImageKnifeComponent({ ImageKnifeOption:
|
||||
{
|
||||
|
@ -134,12 +148,12 @@ ImageKnifeComponent({ ImageKnifeOption:
|
|||
}).width(100).height(100)
|
||||
```
|
||||
|
||||
|
||||
## 接口说明
|
||||
|
||||
### ImageKnifeOption参数列表
|
||||
|
||||
| 参数名称 | 入参内容 | 功能简介 |
|
||||
|-----------------------|---------------------------|-----------------|
|
||||
|-----------------------|--------------------------------|-----------------|
|
||||
| loadSrc | string、PixelMap、Resource | 主图展示 |
|
||||
| placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
|
||||
| errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
|
||||
|
@ -158,20 +172,24 @@ ImageKnifeComponent({ ImageKnifeOption:
|
|||
| transformation | PixelMapTransformation | 图片变换(可选) |
|
||||
|
||||
### ImageKnife接口
|
||||
|
||||
| 参数名称 | 入参内容 | 功能简介 |
|
||||
|------------------|---------------------------|---------------|
|
||||
|------------------|-------------------------------------------------------------------------------------------------------|---------------|
|
||||
| initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 |
|
||||
| initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 |
|
||||
| preLoadCache | url:string | 预加载并返回文件缓存路径 |
|
||||
| getCacheImage | url: string, cacheType: CacheType | 从内存或文件缓存中获取资源 |
|
||||
| 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请求头 |
|
||||
| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 |
|
||||
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 |
|
||||
|
||||
## 约束与限制
|
||||
|
||||
在下述版本验证通过:
|
||||
DevEco Studio 5.0 Canary3(5.0.3.221)--SDK:API12
|
||||
|
||||
## 贡献代码
|
||||
|
||||
使用过程中发现任何问题都可以提 [issue](https://gitee.com/openharmony-tpc/ImageKnife/issues)
|
||||
|
@ -182,4 +200,5 @@ DevEco Studio 5.0 Canary3(5.0.3.221)--SDK:API12
|
|||
本项目基于 [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE) ,请自由的享受和参与开源。
|
||||
|
||||
## 遗留问题
|
||||
|
||||
- 添加组件闪动问题
|
|
@ -14,13 +14,14 @@
|
|||
*/
|
||||
import { ImageKnifeComponent,BlurTransformation } from '@ohos/imageknife';
|
||||
import fs from '@ohos.file.fs';
|
||||
import image from '@ohos.multimedia.image';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct SingleImage {
|
||||
scroller: Scroller = new Scroller;
|
||||
localFile: string = getContext(this).filesDir + "/icon.png"
|
||||
|
||||
@State pixelMap:PixelMap | undefined = undefined;
|
||||
aboutToAppear(): void {
|
||||
// 拷贝本地文件
|
||||
let icon: Uint8Array = getContext(this).resourceManager.getMediaContentSync($r("app.media.startIcon"));
|
||||
|
@ -28,6 +29,9 @@ struct SingleImage {
|
|||
fs.writeSync(file.fd, icon.buffer);
|
||||
fs.fsyncSync(file.fd);
|
||||
fs.closeSync(file);
|
||||
getContext().resourceManager.getMediaContentSync( $r("app.media.aaa"))
|
||||
.buffer as ArrayBuffer;
|
||||
|
||||
}
|
||||
|
||||
build() {
|
||||
|
@ -80,11 +84,34 @@ struct SingleImage {
|
|||
transformation: new BlurTransformation(10)
|
||||
}
|
||||
}).width(100).height(100)
|
||||
Text("自定义下载")
|
||||
.fontSize(30)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: this.pixelMap,
|
||||
placeholderSrc: $r("app.media.loading"),
|
||||
errorholderSrc: $r("app.media.app_icon"),
|
||||
objectFit: ImageFit.Contain,
|
||||
}
|
||||
}).width(100).height(100)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
changePic(buffer: ArrayBuffer){
|
||||
let imageSource: image.ImageSource = image.createImageSource(buffer);
|
||||
if (imageSource) {
|
||||
let decodingOptions: image.DecodingOptions = {
|
||||
editable: true,
|
||||
}
|
||||
imageSource.createPixelMap(decodingOptions,(err,pixelMap)=>{
|
||||
this.pixelMap = pixelMap;
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义下载方法
|
||||
|
|
|
@ -73,6 +73,7 @@ export class ImageKnife {
|
|||
addHeader(key: string, value: Object) {
|
||||
this.headerMap.set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局设置请求头调用方法
|
||||
* @param options 请求头数组
|
||||
|
@ -82,6 +83,7 @@ export class ImageKnife {
|
|||
this.headerMap.set(value.key, value.value)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个请求头属性
|
||||
* @param key 请求头属性
|
||||
|
@ -89,6 +91,7 @@ export class ImageKnife {
|
|||
deleteHeader(key: string) {
|
||||
this.headerMap.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义的内存缓存
|
||||
* @param newMemoryCache 自定义内存缓存
|
||||
|
@ -128,17 +131,21 @@ export class ImageKnife {
|
|||
getFileCache(): FileCache {
|
||||
return this.fileCache as FileCache
|
||||
}
|
||||
|
||||
/**
|
||||
* 预加载到文件缓存
|
||||
* @param loadSrc 图片地址url
|
||||
* @returns 返回文件缓存路径
|
||||
*/
|
||||
preLoadCache(loadSrc: string): Promise<string> {
|
||||
preLoadCache(loadSrc: string | ImageKnifeOption): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let imageKnifeOption = new ImageKnifeOption()
|
||||
imageKnifeOption.loadSrc = loadSrc
|
||||
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
|
||||
let fileKey = engineKeyImpl.generateFileKey(loadSrc)
|
||||
if (loadSrc instanceof ImageKnifeOption) {
|
||||
imageKnifeOption = loadSrc
|
||||
} else {
|
||||
imageKnifeOption.loadSrc = loadSrc;
|
||||
}
|
||||
let fileKey = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature)
|
||||
let cachePath = ImageKnife.getInstance().getFileCache().getFileToPath(fileKey)
|
||||
if (cachePath == null || cachePath == "" || cachePath == undefined) {
|
||||
let request = new ImageKnifeRequest(
|
||||
|
@ -159,18 +166,21 @@ export class ImageKnife {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 从内存或文件缓存中获取图片数据
|
||||
* @param url 图片地址url
|
||||
* @param cacheType 缓存策略
|
||||
* @returns 图片数据
|
||||
* @param signature key自定义信息
|
||||
*/
|
||||
getCacheImage(loadSrc: string,
|
||||
cacheType: CacheStrategy = CacheStrategy.Default): Promise<ImageKnifeData | undefined> {
|
||||
cacheType: CacheStrategy = CacheStrategy.Default, signature?: string): Promise<ImageKnifeData | undefined> {
|
||||
let option: ImageKnifeOption = {
|
||||
loadSrc: loadSrc
|
||||
loadSrc: loadSrc,
|
||||
signature:signature
|
||||
}
|
||||
let engineKeyImpl: IEngineKey = new DefaultEngineKey()
|
||||
let engineKeyImpl: IEngineKey = this.getEngineKeyImpl();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (cacheType == CacheStrategy.Memory) {
|
||||
|
@ -184,6 +194,40 @@ export class ImageKnife {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param url 图片地址url
|
||||
* @param pixelMap 图片
|
||||
* @param cacheType 缓存策略
|
||||
* @param signature key自定义信息
|
||||
*/
|
||||
putCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) {
|
||||
let memoryKey = this.getEngineKeyImpl()
|
||||
.generateMemoryKey(url, ImageKnifeRequestSource.SRC, { loadSrc: url, signature: signature });
|
||||
let fileKey = this.getEngineKeyImpl().generateFileKey(url, signature);
|
||||
let imageKnifeData: ImageKnifeData = { source: pixelMap, imageWidth: 0, imageHeight: 0 };
|
||||
switch (cacheType) {
|
||||
case CacheStrategy.Default:
|
||||
this.saveMemoryCache(memoryKey, imageKnifeData);
|
||||
this.saveFileCache(fileKey, this.pixelMapToArrayBuffer(pixelMap));
|
||||
break;
|
||||
case CacheStrategy.File:
|
||||
this.saveFileCache(fileKey, this.pixelMapToArrayBuffer(pixelMap));
|
||||
break
|
||||
case CacheStrategy.Memory:
|
||||
this.saveMemoryCache(memoryKey, imageKnifeData);
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private pixelMapToArrayBuffer(pixelMap: PixelMap): ArrayBuffer {
|
||||
let imageInfo = pixelMap.getImageInfoSync();
|
||||
let readBuffer: ArrayBuffer = new ArrayBuffer(imageInfo.size.height * imageInfo.size.width * 4);
|
||||
pixelMap.readPixelsToBufferSync(readBuffer);
|
||||
return readBuffer
|
||||
|
||||
}
|
||||
|
||||
private readMemoryCache(loadSrc: string, option: ImageKnifeOption, engineKey: IEngineKey): ImageKnifeData | undefined {
|
||||
let memoryKey = engineKey.generateMemoryKey(loadSrc, ImageKnifeRequestSource.SRC, option)
|
||||
return ImageKnife.getInstance()
|
||||
|
@ -225,6 +269,7 @@ export class ImageKnife {
|
|||
onComplete(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有文件缓存
|
||||
* @returns
|
||||
|
@ -268,4 +313,7 @@ export class ImageKnife {
|
|||
this.dispatcher.setEngineKeyImpl(impl);
|
||||
}
|
||||
|
||||
getEngineKeyImpl(): IEngineKey {
|
||||
return this.dispatcher.getEngineKeyImpl();
|
||||
}
|
||||
}
|
|
@ -32,7 +32,12 @@ import { FileTypeUtil } from './utils/FileTypeUtil';
|
|||
import util from '@ohos.util';
|
||||
import { IEngineKey } from './key/IEngineKey';
|
||||
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
||||
import { ImageKnifeRequestWithSource , ImageKnifeRequestSource , RequestJobResult , RequestJobRequest } from './model/ImageKnifeData'
|
||||
import {
|
||||
ImageKnifeRequestWithSource,
|
||||
ImageKnifeRequestSource,
|
||||
RequestJobResult,
|
||||
RequestJobRequest
|
||||
} from './model/ImageKnifeData'
|
||||
|
||||
export class ImageKnifeDispatcher {
|
||||
// 最大并发
|
||||
|
@ -45,8 +50,19 @@ export class ImageKnifeDispatcher {
|
|||
private engineKey: IEngineKey = new DefaultEngineKey();
|
||||
|
||||
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource): boolean {
|
||||
let memoryCache: ImageKnifeData | undefined = ImageKnife.getInstance()
|
||||
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption))
|
||||
let memoryCache: ImageKnifeData | undefined;
|
||||
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||
memoryCache = {
|
||||
source: request.imageKnifeOption.loadSrc as image.PixelMap,
|
||||
imageWidth: 0,
|
||||
imageHeight: 0,
|
||||
}
|
||||
} else {
|
||||
memoryCache = ImageKnife.getInstance()
|
||||
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption));
|
||||
}
|
||||
|
||||
|
||||
if (memoryCache !== undefined) {
|
||||
// 画主图
|
||||
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||
|
@ -114,7 +130,8 @@ export class ImageKnifeDispatcher {
|
|||
customGetImage: currentRequest.imageKnifeOption.customGetImage,
|
||||
onlyRetrieveFromCache: currentRequest.imageKnifeOption.onlyRetrieveFromCache,
|
||||
transformation: currentRequest.imageKnifeOption.transformation,
|
||||
writeCacheStrategy: ImageKnife.getInstance().isFileCacheInit() ? currentRequest.imageKnifeOption.writeCacheStrategy : CacheStrategy.Memory, // 未初始化文件缓存时,不写文件缓存
|
||||
writeCacheStrategy: ImageKnife.getInstance()
|
||||
.isFileCacheInit() ? currentRequest.imageKnifeOption.writeCacheStrategy : CacheStrategy.Memory, // 未初始化文件缓存时,不写文件缓存
|
||||
engineKey: this.engineKey,
|
||||
signature: currentRequest.imageKnifeOption.signature,
|
||||
requestSource
|
||||
|
@ -215,6 +232,10 @@ export class ImageKnifeDispatcher {
|
|||
setEngineKeyImpl(impl: IEngineKey): void {
|
||||
this.engineKey = impl;
|
||||
}
|
||||
|
||||
getEngineKeyImpl(): IEngineKey {
|
||||
return this.engineKey;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,10 +342,17 @@ async function requestJob(request: RequestJobRequest): Promise<RequestJobResult
|
|||
}
|
||||
}
|
||||
} else if ((request.src as Resource).id !== undefined) { //从资源文件获取
|
||||
let res = request.src as Resource;
|
||||
if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) {
|
||||
resBuf = request.context.resourceManager.getMediaContentSync((request.src as Resource).id).buffer as ArrayBuffer
|
||||
resBuf = request.context.createModuleContext(res.moduleName)
|
||||
.resourceManager
|
||||
.getMediaContentSync(res.id)
|
||||
.buffer as ArrayBuffer;
|
||||
} else if (resBuf == undefined && request.requestSource != ImageKnifeRequestSource.SRC) {
|
||||
resBuf = request.context.resourceManager.getMediaContentSync((request.src as Resource).id).buffer as ArrayBuffer
|
||||
resBuf = request.context.createModuleContext(res.moduleName)
|
||||
.resourceManager
|
||||
.getMediaContentSync(res.id)
|
||||
.buffer as ArrayBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue