Compare commits

..

4 Commits

Author SHA1 Message Date
yaofangyong ecb2494582
Pre Merge pull request !327 from yaofangyong/3.x 2024-07-29 03:55:20 +00:00
zgf 4872cc64f7 修复错误图显示以及heic格式匹配
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-07-29 11:27:22 +08:00
zgf a792587c93 修复自定义下载失败无失败回调以及新增全局自定义下载接口
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-07-26 15:17:13 +08:00
zgf 44b3ca48ef 修复自定义下载失败无失败回调以及新增全局自定义下载接口
Signed-off-by: zgf <zenggaofeng2@h-partners.com>
2024-07-26 15:15:47 +08:00
11 changed files with 180 additions and 10 deletions

View File

@ -1,3 +1,9 @@
## 3.0.1-rc.2
- 修复自定义下载失败无失败回调
- 增加全局配置自定义下载接口
- 修复主图相同,错误图不同导致只显示一个错误图
- heic格式图片文件魔数从第五位开始匹配
## 3.0.1-rc.1 ## 3.0.1-rc.1
- 新增ImageKnifeAnimatorComponent控制动图组件 - 新增ImageKnifeAnimatorComponent控制动图组件
- 修复部分heif图无法解码 - 修复部分heif图无法解码

View File

@ -319,6 +319,7 @@ ImageKnifeAnimatorComponent({
| addHeader | key: string, value: Object | 全局添加http请求头 | | addHeader | key: string, value: Object | 全局添加http请求头 |
| setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 | | setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 |
| deleteHeader | key: string | 全局删除http请求头 | | deleteHeader | key: string | 全局删除http请求头 |
| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined> | 全局设置自定义下载 |
| setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 | | setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 |
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 | | putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 |
| removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 | | removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 |

View File

@ -48,6 +48,12 @@ struct Index {
}); });
}) })
Button("全局自定义下载").margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestSetCustomImagePage',
});
})
Button("多图 + LazyForEach").margin({top:10}).onClick(()=>{ Button("多图 + LazyForEach").margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/ManyPhotoShowPage', uri: 'pages/ManyPhotoShowPage',
@ -135,7 +141,12 @@ struct Index {
uri: 'pages/TestRemoveCache', uri: 'pages/TestRemoveCache',
}); });
}) })
Button("测试错误图显示").margin({top:10}).onClick(()=>{
router.push({
uri: 'pages/TestErrorHolderPage',
});
})
Button("测试媒体url").margin({top:10}).onClick(()=>{ Button("测试媒体url").margin({top:10}).onClick(()=>{
router.push({ router.push({
uri: 'pages/dataShareUriLoadPage', uri: 'pages/dataShareUriLoadPage',

View File

@ -36,6 +36,10 @@ struct LoadStatePage {
}, },
border: { radius: 50 } border: { radius: 50 }
} }
@State imageKnifeOption1: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon')
}
@State message: string = ""
@State currentWidth: number = 200 @State currentWidth: number = 200
@State currentHeight: number = 200 @State currentHeight: number = 200
@State typeValue: string = "" @State typeValue: string = ""
@ -78,11 +82,33 @@ struct LoadStatePage {
Text(this.typeValue) Text(this.typeValue)
ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth) ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth)
.margin({ top: 20 }) .margin({ top: 20 })
Button("自定义下载失败").onClick(()=>{
this.imageKnifeOption1 = {
loadSrc: "abc",
placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'),
customGetImage:custom,
onLoadListener: {
onLoadFailed:(err)=>{
this.message = "err:" + err
}
}
}
}).margin({ top: 20 })
Text(this.message).fontSize(20).margin({ top: 20 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).height(this.currentHeight).width(this.currentWidth)
.margin({ top: 20 })
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
} }
}
// 自定义下载方法
@Concurrent
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> {
console.info("ImageKnife:: custom download" + src)
// 举例写死从本地文件读取,也可以自己请求网络图片
return undefined
} }

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry
@Component
struct TestErrorHolderPage {
build() {
Column() {
Text("ImageKnifeComponent1").fontSize(20)
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: "abc",
errorholderSrc:$r('app.media.failed')
}
}).width(200).height(200)
Text("ImageKnifeComponent2").fontSize(20)
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: "abc",
errorholderSrc:$r('app.media.startIcon')
}
}).width(200).height(200)
Text("ImageKnifeComponent2").fontSize(20)
ImageKnifeComponent({
imageKnifeOption: {
loadSrc: "abc",
errorholderSrc:$r('app.media.mask_starfish')
}
}).width(200).height(200)
}
.height('100%') .width('100%')
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry
@Component
struct TestSetCustomImagePage {
@State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading')
}
aboutToAppear(): void {
ImageKnife.getInstance().setCustomGetImage(custom)
}
aboutToDisappear(): void {
ImageKnife.getInstance().setCustomGetImage()
}
build() {
Column() {
Button("自定义下载a").onClick(()=>{
this.imageKnifeOption = {
loadSrc: "aaa",
placeholderSrc: $r('app.media.loading')
}
})
Button("自定义下载b").onClick(()=>{
this.imageKnifeOption = {
loadSrc: "bbb",
placeholderSrc: $r('app.media.loading')
}
})
Button("自定义下载c").onClick(()=>{
this.imageKnifeOption = {
loadSrc: "ccc",
placeholderSrc: $r('app.media.loading')
}
})
ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption
}).width(300)
.height(300)
}
.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.pngSample").id).buffer as ArrayBuffer
}

View File

@ -20,6 +20,8 @@
"pages/TestRemoveCache", "pages/TestRemoveCache",
"pages/dataShareUriLoadPage", "pages/dataShareUriLoadPage",
"pages/TestCommonImage", "pages/TestCommonImage",
"pages/ImageAnimatorPage" "pages/ImageAnimatorPage",
"pages/TestSetCustomImagePage",
"pages/TestErrorHolderPage"
] ]
} }

View File

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

View File

@ -38,7 +38,7 @@ export class ImageKnife {
private _isRequestInSubThread: boolean = true; private _isRequestInSubThread: boolean = true;
//定义全局网络请求header map //定义全局网络请求header map
headerMap: Map<string, Object> = new Map<string, Object>(); headerMap: Map<string, Object> = new Map<string, Object>();
customGetImage: ((context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>) | undefined = undefined
public static getInstance(): ImageKnife { public static getInstance(): ImageKnife {
if (!ImageKnife.instance) { if (!ImageKnife.instance) {
ImageKnife.instance = new ImageKnife(); ImageKnife.instance = new ImageKnife();
@ -380,4 +380,14 @@ export class ImageKnife {
getEngineKeyImpl(): IEngineKey { getEngineKeyImpl(): IEngineKey {
return this.dispatcher.getEngineKeyImpl(); return this.dispatcher.getEngineKeyImpl();
} }
/**
* 全局设置自定义下载
* @param customGetImage 自定义请求函数
*/
setCustomGetImage(customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>) {
this.customGetImage = customGetImage
}
getCustomGetImage(): undefined | ((context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>){
return this.customGetImage
}
} }

View File

@ -179,7 +179,9 @@ export class ImageKnifeDispatcher {
isAnimator:isAnimator isAnimator:isAnimator
} }
if(request.customGetImage == undefined) {
request.customGetImage = ImageKnife.getInstance().getCustomGetImage()
}
if (ImageKnife.getInstance().isRequestInSubThread){ if (ImageKnife.getInstance().isRequestInSubThread){
// 启动线程下载和解码主图 // 启动线程下载和解码主图
LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:" + currentRequest.imageKnifeOption.loadSrc) LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:" + currentRequest.imageKnifeOption.loadSrc)
@ -253,9 +255,9 @@ export class ImageKnifeDispatcher {
if (requestWithSource.source === ImageKnifeRequestSource.SRC && if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) { requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
if (this.showFromMemomry(currentRequest, requestWithSource.request.imageKnifeOption.errorholderSrc, if (this.showFromMemomry(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
ImageKnifeRequestSource.ERROR_HOLDER) === false) { ImageKnifeRequestSource.ERROR_HOLDER) === false) {
this.getAndShowImage(currentRequest, requestWithSource.request.imageKnifeOption.errorholderSrc, this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
ImageKnifeRequestSource.ERROR_HOLDER); ImageKnifeRequestSource.ERROR_HOLDER);
} }
} }
@ -399,6 +401,7 @@ async function requestJob(request: RequestJobRequest, requestList?: List<ImageKn
if (resBuf === undefined) { if (resBuf === undefined) {
LogUtil.log("customGetImage customGetImage"); LogUtil.log("customGetImage customGetImage");
resBuf = await request.customGetImage(request.context, request.src) resBuf = await request.customGetImage(request.context, request.src)
loadError = resBuf == undefined ? "customGetImage loadFile" : loadError
// 保存文件缓存 // 保存文件缓存
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) { if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug不能直接获取resBuf.byteLength let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug不能直接获取resBuf.byteLength

View File

@ -58,7 +58,7 @@ export class FileTypeUtil {
const bufferList = this.fileSignatureMap[fileType]; const bufferList = this.fileSignatureMap[fileType];
for (let i = 0; i < bufferList.length; i++) { for (let i = 0; i < bufferList.length; i++) {
let signature = bufferList[i]; let signature = bufferList[i];
if (this.matchesSignature(fileData, signature)) { if (this.matchesSignature(fileData, signature,fileType)) {
hasMatched = true; hasMatched = true;
matchedFileType = fileType; matchedFileType = fileType;
break break
@ -75,12 +75,12 @@ export class FileTypeUtil {
} }
matchesSignature(fileData: Uint8Array, signature: Uint8Array): boolean { matchesSignature(fileData: Uint8Array, signature: Uint8Array,fileType:string): boolean {
if (fileData.length < signature.length) { if (fileData.length < signature.length) {
return false; // 文件长度不足,无法匹配魔数 return false; // 文件长度不足,无法匹配魔数
} }
for (let i = 0; i < signature.length; i++) { for (let i = fileType == "heic" ? 4 : 0; i < signature.length; i++) {
if (fileData[i] !== signature[i]) { if (fileData[i] !== signature[i]) {
return false; // 魔数不匹配 return false; // 魔数不匹配
} }