Merge branch 'master' of https://gitee.com/zhou_li_sheng/ImageKnife_1
# Conflicts: # entry/src/main/ets/pages/manyPhotoShowPage.ets # imageknife/src/main/ets/components/imageknife/ImageKnife.ets # imageknife/src/main/ets/components/imageknife/ImageKnifeComponent.ets # imageknife/src/main/ets/components/imageknife/RequestOption.ets # imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets # imageknife/src/main/ets/components/imageknife/networkmanage/HttpDownloadClient.ets # imageknife/src/main/ets/components/imageknife/utils/FileTypeUtil.ets # imageknife/src/main/ets/components/imageknife/utils/base/EasyLinkedHashMap.ets
This commit is contained in:
commit
8ea608a83a
|
@ -3,7 +3,7 @@
|
|||
"bundleName": "com.openharmony.imageknife",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "2.1.1-rc.0",
|
||||
"versionName": "2.1.1-rc.3",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name",
|
||||
"distributedNotificationEnabled": true
|
||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,6 +1,18 @@
|
|||
## 2.1.1-rc.3
|
||||
|
||||
- 门面类ImageKnife新增pauseRequests接口,全局暂停请求
|
||||
- 门面类ImageKnife新增resumeRequests接口,全局恢复暂停
|
||||
|
||||
## 2.1.1-rc.2
|
||||
|
||||
- gif解码改为imageSource解码,不在对worker强依赖
|
||||
- 下载接口修改为http.requestInStream
|
||||
|
||||
## 2.1.1-rc.1
|
||||
|
||||
- 新增自定义key参数配置
|
||||
- 新增MemoryLruCache主动调用PixelMap的release方法,释放native的PixelMap内存
|
||||
- 新增ImageSource主动调用release方法释放native持有的ImageSource内存
|
||||
|
||||
## 2.1.1-rc.0
|
||||
|
||||
|
@ -8,7 +20,7 @@
|
|||
|
||||
## 2.1.0
|
||||
|
||||
- ArkTs语法整改:
|
||||
- ArkTs语法适配:
|
||||
|
||||
globalThis.ImageKnife方式已经不可使用
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ ohpm install @ohos/imageknife
|
|||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
"@ohos/imageknife": "^2.0.6"
|
||||
"@ohos/imageknife": "^2.1.1-rc.3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -468,9 +468,11 @@ request.skipMemoryCache(true)
|
|||
### ImageKnife 启动器/门面类
|
||||
|
||||
| 方法名 | 入参 | 接口描述 |
|
||||
|---------------------------------|------------------------|-------------------|
|
||||
| ------------------------------- | ---------------------- | ---------------------------------- |
|
||||
| call(request: RequestOption) | request: RequestOption | 根据用户配置参数具体执行加载流程 |
|
||||
| preload(request: RequestOption) | request: RequestOption | 根据用户配置参数具体执行预加载流程 |
|
||||
| pauseRequests() | | 全局暂停请求 |
|
||||
| resumeRequests() | | 全局恢复暂停 |
|
||||
|
||||
### 缓存策略相关
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"name": "entry",
|
||||
"description": "example description",
|
||||
"repository": {},
|
||||
"version": "2.1.1-rc.0",
|
||||
"version": "2.1.1-rc.3",
|
||||
"dependencies": {
|
||||
"@ohos/imageknife": "file:../imageknife",
|
||||
"@ohos/disklrucache": "^2.0.2-rc.0"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
import { EngineKeyFactories, EngineKeyInterface, RequestOption } from '@ohos/imageknife'
|
||||
import { ObjectKey } from '@ohos/imageknife/src/main/ets/components/imageknife/ObjectKey';
|
||||
import { ObjectKey } from '@ohos/imageknife';
|
||||
|
||||
export class CustomEngineKeyImpl implements EngineKeyInterface {
|
||||
redefineUrl: (loadSrc: string) => string;
|
||||
|
|
|
@ -23,8 +23,10 @@ struct basicTestFileIOPage {
|
|||
@State filePath: string = '查看featureAbility路径';
|
||||
appFilePath = '';
|
||||
appCachePath = '';
|
||||
@State imageHint: string = ''
|
||||
@State imageFile: string = '文字提醒'
|
||||
@State imageHint: string = '文字提醒1'
|
||||
@State imageHint2: string = '文字提醒2'
|
||||
@State imageFile: string = ''
|
||||
|
||||
@State imageRes: Resource = $r('app.media.pngSample')
|
||||
@State imagePixelMap?: PixelMap = undefined
|
||||
@State normalPixelMap: boolean = false;
|
||||
|
@ -63,7 +65,7 @@ struct basicTestFileIOPage {
|
|||
.margin({ top: 10 })
|
||||
.onClick(() => {
|
||||
if(this.appFilePath == '' || this.appFilePath == null){
|
||||
this.appFilePath = 'appFilePath未取到值,请按顺序从上往下,从左往右依次测试'
|
||||
this.imageHint = 'appFilePath未取到值,请按顺序从上往下,从左往右依次测试'
|
||||
return
|
||||
}
|
||||
console.log('files目录创建Folder1和Folder2 验证statSync mkdirSync')
|
||||
|
@ -94,12 +96,13 @@ struct basicTestFileIOPage {
|
|||
console.log('basicTestFileIOPage - 本地加载资源err' + JSON.stringify(err as BusinessError));
|
||||
})
|
||||
})
|
||||
Text(this.imageHint2)
|
||||
Button('copy:Folder1至Folder2, 验证copyFileSync')
|
||||
.margin({ top: 10 })
|
||||
.onClick(() => {
|
||||
console.log('copy:Folder1至Folder2, 验证copyFileSync')
|
||||
if(this.appFilePath == '' || this.appFilePath == null){
|
||||
this.appFilePath = 'appFilePath未取到值,请按顺序从上往下,从左往右依次测试'
|
||||
this.imageHint2 = 'appFilePath未取到值,请按顺序从上往下,从左往右依次测试'
|
||||
return
|
||||
}
|
||||
let filePath1 = this.appFilePath + '/Folder1/jpgSample.gif';
|
||||
|
|
|
@ -41,7 +41,9 @@ struct BasicTestResourceManagerPage {
|
|||
let arrayBuffer = this.typedArrayToBuffer(data);
|
||||
let filetypeUtil = new FileTypeUtil();
|
||||
let fileType = filetypeUtil.getFileType(arrayBuffer);
|
||||
if(fileType != null) {
|
||||
this.fileTypeStr = fileType;
|
||||
}
|
||||
})
|
||||
.catch((err:BusinessError) => {
|
||||
console.log('basicTestFileIOPage - 本地加载资源err' + JSON.stringify(err));
|
||||
|
@ -63,7 +65,9 @@ struct BasicTestResourceManagerPage {
|
|||
.decode(data);
|
||||
let filetypeUtil = new FileTypeUtil();
|
||||
let fileType = filetypeUtil.getFileType(arrayBuffer);
|
||||
if(fileType != null) {
|
||||
this.fileTypeStr = fileType;
|
||||
}
|
||||
})
|
||||
.catch((err:BusinessError) => {
|
||||
console.log('basicTestFileIOPage - 本地加载资源err' + JSON.stringify(err));
|
||||
|
|
|
@ -220,6 +220,11 @@ struct IndexFunctionDemo {
|
|||
console.log("pages/manyPhotoShowPage 页面跳转")
|
||||
router.pushUrl({ url: "pages/manyPhotoShowPage" });
|
||||
}).margin({ top: 15 })
|
||||
Button("图片加载暂停和恢复")
|
||||
.onClick(() => {
|
||||
console.log("pages/manyPhotoShowPage 页面跳转")
|
||||
router.pushUrl({ url: "pages/photosPausedResumedPage" });
|
||||
}).margin({ top: 15 })
|
||||
Button("部分url测试")
|
||||
.onClick(() => {
|
||||
console.log("pages/tempUrlTestPage 页面跳转")
|
||||
|
@ -248,6 +253,17 @@ struct IndexFunctionDemo {
|
|||
router.pushUrl({ url: "pages/testGifLoadWithWorkerPage" });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
}.width('100%').height(60).backgroundColor(Color.Pink)
|
||||
Text("测试图片加载稳定").fontSize(15)
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Button("测试多张网络图片加载速度")
|
||||
.onClick(() => {
|
||||
router.pushUrl({ url: "pages/testManyNetImageLoadWithPage" });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
Button("测试多张gif加载位置")
|
||||
.onClick(() => {
|
||||
router.pushUrl({ url: "pages/testManyGifLoadWithPage" });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
}.width('100%').height(60).backgroundColor(Color.Pink)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
|
|
|
@ -31,36 +31,6 @@ struct ManyPhotoShowPage {
|
|||
build() {
|
||||
Column() {
|
||||
|
||||
Button('点击暂停加载')
|
||||
.margin({top:10,bottom:5})
|
||||
.onClick(()=>{
|
||||
let imageKnife = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if(imageKnife!= undefined){
|
||||
imageKnife.pauseRequests()
|
||||
}
|
||||
})
|
||||
|
||||
Button('点击重新加载')
|
||||
.margin({top:10,bottom:5})
|
||||
.onClick(()=>{
|
||||
let imageKnife = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if(imageKnife!= undefined){
|
||||
imageKnife.resumeRequests()
|
||||
}
|
||||
})
|
||||
|
||||
Button('设置磁盘存储为50M')
|
||||
.margin({top:10,bottom:5})
|
||||
.onClick(()=>{
|
||||
if(ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
||||
let disk: DiskLruCache | undefined = (ImageKnifeGlobal.getInstance().getImageKnife())?.getDiskMemoryCache();
|
||||
if(disk != undefined) {
|
||||
disk.setMaxSize(50 * 1024 * 1024)
|
||||
Prompt.showToast({ message: "设置成功" })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
List({ space: 20, scroller: this.elementScroller }) {
|
||||
LazyForEach(this.data, (item: Material, index) => {
|
||||
ListItem() {
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {ImageKnifeComponent, ScaleType} from '@ohos/imageknife'
|
||||
import {ImageKnifeOption} from '@ohos/imageknife'
|
||||
import {ImageKnifeGlobal} from '@ohos/imageknife'
|
||||
import {RotateImageTransformation} from '@ohos/imageknife'
|
||||
import {Material} from './model/Material'
|
||||
import {TestDataSource} from './model/TestDataSource'
|
||||
import {DiskLruCache} from '@ohos/disklrucache'
|
||||
import ArkWorker from '@ohos.worker'
|
||||
import Prompt from '@system.prompt'
|
||||
@Entry
|
||||
@Component
|
||||
struct photosPausedResumedPage {
|
||||
private data: TestDataSource = new TestDataSource();
|
||||
|
||||
private elementScroller: Scroller = new Scroller()
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
|
||||
Button('点击暂停加载')
|
||||
.margin({top:10,bottom:5})
|
||||
.onClick(()=>{
|
||||
let imageKnife = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if(imageKnife!= undefined){
|
||||
imageKnife.pauseRequests()
|
||||
}
|
||||
})
|
||||
|
||||
Button('点击重新加载')
|
||||
.margin({top:10,bottom:5})
|
||||
.onClick(()=>{
|
||||
let imageKnife = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if(imageKnife!= undefined){
|
||||
imageKnife.resumeRequests()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
List({ space: 20, scroller: this.elementScroller }) {
|
||||
LazyForEach(this.data, (item: Material, index) => {
|
||||
ListItem() {
|
||||
Column() {
|
||||
Stack({ alignContent: Alignment.BottomEnd }) {
|
||||
// 滤镜图片
|
||||
ImageKnifeComponent({ imageKnifeOption: {
|
||||
loadSrc: item.thumbnail,
|
||||
mainScaleType: ScaleType.FIT_XY,
|
||||
} })
|
||||
}
|
||||
.width(56).height(56)
|
||||
//滤镜标题
|
||||
Text(item.name)
|
||||
.fontSize(10)
|
||||
.maxLines(1)
|
||||
.fontColor(Color.White)
|
||||
.textAlign(TextAlign.Center)
|
||||
.layoutWeight(1)
|
||||
.width('100%')
|
||||
.backgroundColor(Color.Orange)
|
||||
}
|
||||
.width(56)
|
||||
.height(72)
|
||||
.clip(true)
|
||||
.borderRadius(4)
|
||||
}
|
||||
}, (item: Material) => item.material_id)
|
||||
}
|
||||
.listDirection(Axis.Horizontal)
|
||||
.width('100%')
|
||||
.height(72)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,8 @@ struct PngjTestCasePage {
|
|||
name: 'readPngImageAsync'
|
||||
})
|
||||
pngj.readPngImageAsync(png_worker, this.pngSource2!, {pngCallback: (sender:ArrayBuffer, value:Record<string,Object>) => {
|
||||
this.pngSource1 = sender
|
||||
this.pngSource2 = sender
|
||||
this.hint8 = '重新获取buffer才能测试'
|
||||
this.hint2 = 'img with=' + value.width + ' img height=' + value.height
|
||||
+ ' img depth=' + value.depth + ' img ctype=' + value.ctype
|
||||
this.pngdecodeRun2 = false;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ImageKnife, ImageKnifeComponent, ImageKnifeGlobal, ImageKnifeOption } from "@ohos/imageknife"
|
||||
import worker from '@ohos.worker';
|
||||
|
||||
let gifUrl = "https://gw.alicdn.com/tfs/TB1E3H5t8Bh1e4jSZFhXXcC9VXa-198-198.gif"
|
||||
|
||||
let data: string[] = [
|
||||
'https://media.giphy.com/media/hVgagDPf1IRFK/giphy.gif',
|
||||
'https://placehold.co/600x400/000000/FFFFFF/png',
|
||||
'https://s1.aigei.com/src/img/gif/92/922f58ca46c34b3e9947ddd4dc17ec32.gif?imageMogr2/auto-orient/thumbnail/!282x282r/gravity/Center/crop/282x282/quality/85/&e=1735488000&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:YRYJJynbOC0Z_Nl7HunjuRr4-Vk=',
|
||||
'https://placehold.co/600x400/000000/orange/png',
|
||||
'https://s1.aigei.com/src/img/gif/6c/6c907924ef1546d3a593fae3e78b97f6.gif?imageMogr2/auto-orient/thumbnail/!282x282r/gravity/Center/crop/282x282/quality/85/&e=1735488000&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:PozGIimx0mj5m69DQ0Z6qWn7mA0=',
|
||||
'https://placehold.co/600x400/000000/orange/png?text=Hello+World'
|
||||
]
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestManyGifLoadWithPage {
|
||||
private globalGifWorker?: worker.ThreadWorker = undefined
|
||||
@State p1: PixelMap | undefined = undefined
|
||||
@State p2: PixelMap | undefined = undefined
|
||||
@State workerOption: ImageKnifeOption = {
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
};
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text('gif Demo').align(Alignment.Center).fontSize(25).margin(10).fontWeight(FontWeight.Bolder)
|
||||
Row() {
|
||||
Column() {
|
||||
Button('use Origin Image').align(Alignment.Center).fontSize(10).margin(2)
|
||||
Image(gifUrl).width('100%').height(100).backgroundColor(Color.Blue).objectFit(ImageFit.Contain)
|
||||
}.width('50%').backgroundColor(Color.Orange)
|
||||
|
||||
Column() {
|
||||
Button('use ImageKnifeComponent').align(Alignment.Center).fontSize(10).margin(2)
|
||||
ImageKnifeComponent({ imageKnifeOption: { loadSrc: gifUrl } })
|
||||
.width('100%')
|
||||
.height(100)
|
||||
.backgroundColor(Color.Orange)
|
||||
}.width('50%').backgroundColor(Color.Blue)
|
||||
}
|
||||
|
||||
Row() {
|
||||
Column() {
|
||||
Button('use Worker').align(Alignment.Center).fontSize(10).margin(2)
|
||||
.onClick(() => {
|
||||
this.workerOption = {
|
||||
loadSrc: gifUrl,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed')
|
||||
}
|
||||
})
|
||||
ImageKnifeComponent({ imageKnifeOption: this.workerOption })
|
||||
.width('100%')
|
||||
.height(100)
|
||||
.backgroundColor(Color.Blue)
|
||||
}.width('50%').backgroundColor(Color.Orange)
|
||||
|
||||
Column() {
|
||||
Button('logs').align(Alignment.Center).fontSize(10).margin(2)
|
||||
Text('logs').width('100%').height(100).backgroundColor(Color.Orange)
|
||||
}.width('50%').backgroundColor(Color.Blue)
|
||||
}
|
||||
|
||||
Grid() {
|
||||
ForEach(data, (url: string) => {
|
||||
GridItem(){
|
||||
ImageKnifeComponent({imageKnifeOption:{
|
||||
loadSrc:url
|
||||
}}).backgroundColor(0x38393D).width(150).height(100)
|
||||
}
|
||||
})
|
||||
}.rowsGap(2)
|
||||
.columnsGap(2)
|
||||
}.width('100%').height('100%').backgroundColor(0xF1F3F5)
|
||||
}
|
||||
aboutToAppear(){
|
||||
this.globalGifWorker = new worker.ThreadWorker('entry/ets/workers/GifLoadWorker.ts',{
|
||||
type:'classic',
|
||||
name:'ImageKnifeParseGIF'
|
||||
})
|
||||
let imageKnife:ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife()
|
||||
if(imageKnife != undefined){
|
||||
imageKnife?.setGifWorker(this.globalGifWorker)
|
||||
}
|
||||
}
|
||||
aboutToDisappear(){
|
||||
if(this.globalGifWorker){
|
||||
this.globalGifWorker.terminate()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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 { ScaleType, ImageKnifeComponent } from "@ohos/imageknife"
|
||||
|
||||
class CommonDataSource <T> implements IDataSource {
|
||||
private dataArray: T[] = []
|
||||
private listeners: DataChangeListener[] = []
|
||||
|
||||
constructor(element: []) {
|
||||
this.dataArray = element
|
||||
}
|
||||
|
||||
public getData(index: number) {
|
||||
return this.dataArray[index]
|
||||
}
|
||||
|
||||
public totalCount(): number {
|
||||
return this.dataArray.length
|
||||
}
|
||||
|
||||
public addData(index: number, data: T[]): void {
|
||||
this.dataArray = this.dataArray.concat(data)
|
||||
this.notifyDataAdd(index)
|
||||
}
|
||||
|
||||
unregisterDataChangeListener(listener: DataChangeListener): void {
|
||||
const pos = this.listeners.indexOf(listener);
|
||||
if (pos >= 0) {
|
||||
this.listeners.splice(pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
registerDataChangeListener(listener: DataChangeListener): void {
|
||||
if (this.listeners.indexOf(listener) < 0) {
|
||||
this.listeners.push(listener)
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataAdd(index: number): void {
|
||||
this.listeners.forEach((listener: DataChangeListener) => {
|
||||
listener.onDataAdd(index)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestManyNetImageLoadWithPage {
|
||||
@State hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([])
|
||||
private data:Array<string> = [
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/11/2159934215_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/imags/poster/2022/08/02/165937334218556809.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/4350315060_640_360.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/3835072893_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/2821936016_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/11/1311714870_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/4421772097_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/09/05/5898334347_400_225.png',
|
||||
'http://s.yingshidq.com.cn/imags/poster/2022/12/06/167031399911862707.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/11/1405851829_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/3796501624_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/4202181519_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/11/1449894622_1248_702.jpeg',
|
||||
'http://s.yingshidq.com.cn/cover/longbms/2023/08/10/3756558151_1248_702.jpeg'
|
||||
]
|
||||
aboutToAppear() {
|
||||
this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data)
|
||||
}
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Grid() {
|
||||
LazyForEach(this.hotCommendList, (item: string) => {
|
||||
GridItem() {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: item,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
mainScaleType: ScaleType.CENTER_CROP,
|
||||
placeholderScaleType: ScaleType.CENTER_CROP
|
||||
}
|
||||
}).width('100%').height('100%')
|
||||
}.width('45%').height(200)
|
||||
}, (item: string) => JSON.stringify(item))
|
||||
}
|
||||
.columnsTemplate('1fr 1fr')
|
||||
.columnsGap(8)
|
||||
.rowsGap(10)
|
||||
.width('100%')
|
||||
.hitTestBehavior(HitTestMode.None)
|
||||
.maxCount(10)
|
||||
}.margin({ top: 5 })
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import { CropCircleTransformation } from '@ohos/imageknife'
|
|||
import { RoundedCornersTransformation } from '@ohos/imageknife'
|
||||
import {
|
||||
CropCircleWithBorderTransformation
|
||||
} from '@ohos/imageknife/src/main/ets/components/imageknife/transform/CropCircleWithBorderTransformation'
|
||||
} from '@ohos/imageknife'
|
||||
import { RotateImageTransformation } from '@ohos/imageknife'
|
||||
import { CropSquareTransformation } from '@ohos/imageknife'
|
||||
import { CropTransformation } from '@ohos/imageknife'
|
||||
|
|
|
@ -26,11 +26,14 @@
|
|||
"pages/imageknifeTestCaseIndex",
|
||||
"pages/dataShareUriLoadPage",
|
||||
"pages/manyPhotoShowPage",
|
||||
"pages/photosPausedResumedPage",
|
||||
"pages/tempUrlTestPage",
|
||||
"pages/drawFactoryTestPage",
|
||||
"pages/testSingleFrameGifPage",
|
||||
"pages/testGifLoadWithWorkerPage",
|
||||
"pages/OptionTestPage",
|
||||
"pages/SignatureTestPage"
|
||||
"pages/SignatureTestPage",
|
||||
"pages/testManyNetImageLoadWithPage",
|
||||
"pages/testManyGifLoadWithPage"
|
||||
]
|
||||
}
|
|
@ -95,6 +95,7 @@ export { UPNG } from './src/main/ets/components/3rd_party/upng/UPNG'
|
|||
*/
|
||||
export { ImageKnife } from './src/main/ets/components/imageknife/ImageKnife'
|
||||
export { ImageKnifeGlobal } from './src/main/ets/components/imageknife/ImageKnifeGlobal'
|
||||
export { ObjectKey } from './src/main/ets/components/imageknife/ObjectKey'
|
||||
export {RequestOption,Size} from './src/main/ets/components/imageknife/RequestOption'
|
||||
export { ImageKnifeComponent, ScaleType, ScaleTypeHelper } from './src/main/ets/components/imageknife/ImageKnifeComponent'
|
||||
export { ImageKnifeDrawFactory } from './src/main/ets/components/imageknife/ImageKnifeDrawFactory'
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"main": "index.ets",
|
||||
"repository": "https://gitee.com/openharmony-tpc/ImageKnife",
|
||||
"type": "module",
|
||||
"version": "2.1.1-rc.1",
|
||||
"version": "2.1.1-rc.3",
|
||||
"dependencies": {
|
||||
"@ohos/disklrucache": "^2.0.2-rc.0",
|
||||
"@ohos/svg": "^2.1.1-rc.0",
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http:// www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ImageKnife } from '../imageknife/ImageKnife';
|
||||
import { ImageKnifeData } from '../imageknife/ImageKnifeData';
|
||||
import { LruCache } from './LruCache';
|
||||
|
||||
export class MemoryLruCache extends LruCache<string, ImageKnifeData>{
|
||||
constructor(maxsize:number) {
|
||||
super(maxsize)
|
||||
}
|
||||
|
||||
// 移除较少使用的缓存数据
|
||||
trimToSize(tempsize: number) {
|
||||
while (true) {
|
||||
if (tempsize < 0) {
|
||||
this.map.clear()
|
||||
this.size = 0
|
||||
break
|
||||
}
|
||||
if (this.size <= tempsize || this.map.isEmpty()) {
|
||||
break
|
||||
}
|
||||
let delkey = this.map.getFirstKey()
|
||||
let data : ImageKnifeData|undefined = this.map.get(delkey)
|
||||
if(data != undefined){
|
||||
data.release()
|
||||
}
|
||||
this.map.remove(delkey)
|
||||
this.size--
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,11 +17,11 @@ import { RequestOption } from '../../imageknife/RequestOption'
|
|||
|
||||
export interface EngineKeyInterface {
|
||||
// 生成内存缓存
|
||||
generateMemoryCacheKey(loadSrc: string, size: string, transformed: string, dontAnimate: boolean, signature: ObjectKey): string
|
||||
generateMemoryCacheKey(loadSrc: string, size: string, transformed: string, dontAnimate: boolean, signature: ObjectKey | undefined): string
|
||||
// 生成原图变换后的图片的磁盘缓存
|
||||
generateTransformedDiskCacheKey(loadSrc: string, size: string, transformed: string, dontAnimate: boolean, signature: ObjectKey): string
|
||||
generateTransformedDiskCacheKey(loadSrc: string, size: string, transformed: string, dontAnimate: boolean, signature: ObjectKey | undefined): string
|
||||
// 生成原图的磁盘缓存
|
||||
generateOriginalDiskCacheKey(loadSrc: string, signature: ObjectKey): string
|
||||
generateOriginalDiskCacheKey(loadSrc: string, signature: ObjectKey | undefined): string
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
|
||||
import { DiskLruCache } from "@ohos/disklrucache"
|
||||
import { LruCache } from "../cache/LruCache"
|
||||
import { EngineKeyFactories } from "../cache/key/EngineKeyFactories"
|
||||
import { EngineKeyInterface } from "../cache/key/EngineKeyInterface"
|
||||
import { RequestOption } from "../imageknife/RequestOption"
|
||||
|
@ -41,10 +40,11 @@ import worker from '@ohos.worker'
|
|||
import common from '@ohos.app.ability.common'
|
||||
import HashMap from '@ohos.util.HashMap'
|
||||
import LinkedList from '@ohos.util.LinkedList'
|
||||
import { MemoryLruCache } from '../cache/MemoryLruCache'
|
||||
|
||||
export class ImageKnife {
|
||||
static readonly SEPARATOR: string = '/'
|
||||
memoryCache: LruCache<string, ImageKnifeData>;
|
||||
memoryCache: MemoryLruCache;
|
||||
diskMemoryCache: DiskLruCache;
|
||||
dataFetch: IDataFetch;
|
||||
resourceFetch: IResourceFetch<ArrayBuffer>;
|
||||
|
@ -78,7 +78,7 @@ export class ImageKnife {
|
|||
this.pausedMaps = new EasyLinkedHashMap();
|
||||
|
||||
// 构造方法传入size 为保存文件个数
|
||||
this.memoryCache = new LruCache<string, ImageKnifeData>(100);
|
||||
this.memoryCache = new MemoryLruCache(100);
|
||||
|
||||
// 创建disk缓存 传入的size 为多少比特 比如20KB 传入20*1024
|
||||
this.diskMemoryCache = DiskLruCache.create(ImageKnifeGlobal.getInstance().getHapContext());
|
||||
|
@ -100,7 +100,7 @@ export class ImageKnife {
|
|||
|
||||
}
|
||||
|
||||
getMemoryCache(): LruCache<string, ImageKnifeData> {
|
||||
getMemoryCache(): MemoryLruCache {
|
||||
return this.memoryCache;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ export class ImageKnife {
|
|||
return ImageKnifeGlobal.getInstance().getHapContext();
|
||||
}
|
||||
|
||||
setMemoryCache(lrucache: LruCache<string, ImageKnifeData>) {
|
||||
setMemoryCache(lrucache: MemoryLruCache) {
|
||||
this.memoryCache = lrucache;
|
||||
}
|
||||
|
||||
|
@ -177,9 +177,9 @@ export class ImageKnife {
|
|||
// 替代原来的LruCache
|
||||
public replaceLruCache(size: number) {
|
||||
if (this.memoryCache.map.size() <= 0) {
|
||||
this.memoryCache = new LruCache<string, ImageKnifeData>(size);
|
||||
this.memoryCache = new MemoryLruCache(size);
|
||||
} else {
|
||||
let newLruCache = new LruCache<string, ImageKnifeData>(size);
|
||||
let newLruCache = new MemoryLruCache(size);
|
||||
this.memoryCache.foreachLruCache((value: ImageKnifeData, key: string, map: Object) => {
|
||||
newLruCache.put(key, value);
|
||||
})
|
||||
|
@ -218,7 +218,7 @@ export class ImageKnife {
|
|||
|
||||
// 将未删除的所有request [run pend] 放入 [pause]
|
||||
this.pausedMaps.clear()
|
||||
console.log('dodo pauseRequests start1 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
LogUtil.log('dodo pauseRequests start1 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
|
||||
// 将run存入pause
|
||||
let runNode = this.runningMaps.getHead();
|
||||
|
@ -228,7 +228,7 @@ export class ImageKnife {
|
|||
runNode = runNode.next;
|
||||
}
|
||||
this.runningMaps.clear();
|
||||
console.log('dodo pauseRequests start2 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
LogUtil.log('dodo pauseRequests start2 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
|
||||
let pendNode = this.pendingMaps.getHead();
|
||||
while (pendNode) {
|
||||
|
@ -237,15 +237,15 @@ export class ImageKnife {
|
|||
pendNode = pendNode.next
|
||||
}
|
||||
this.pendingMaps.clear()
|
||||
console.log('dodo pauseRequests start3 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
LogUtil.log('dodo pauseRequests start3 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 恢复所有被暂停的请求
|
||||
async resumeRequests(): Promise<void> {
|
||||
await this.mutex.lock(async () => {
|
||||
this.isPaused = false;
|
||||
console.log('dodo resumeRequest start1 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
LogUtil.log('dodo resumeRequest start1 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
// 重启了之后需要把paused 里面的所有request重新发送
|
||||
let headNode = this.pausedMaps.getHead();
|
||||
while (headNode) {
|
||||
|
@ -254,7 +254,7 @@ export class ImageKnife {
|
|||
headNode = headNode.next
|
||||
}
|
||||
this.pausedMaps.clear()
|
||||
console.log('dodo resumeRequest start1 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
LogUtil.log('dodo resumeRequest start1 pausedMaps size=' + this.pausedMaps.size() + ' runMaps Size=' + this.runningMaps.size() + ' pendMaps Size=' + this.pendingMaps.size())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -331,7 +331,7 @@ export class ImageKnife {
|
|||
|
||||
let signature = request.signature;
|
||||
|
||||
if (signature) {
|
||||
if (signature != undefined) {
|
||||
console.log("唯一标识:" + signature.getKey())
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,9 @@ export class ImageKnife {
|
|||
}
|
||||
|
||||
if (hasEqualRunning) {
|
||||
if(tailNode != null && tailNode.value != null) {
|
||||
this.keyEqualPendingToRun(tailNode.value);
|
||||
}
|
||||
} else {
|
||||
this.searchNextKeyToRun();
|
||||
}
|
||||
|
|
|
@ -82,13 +82,14 @@ export struct ImageKnifeComponent {
|
|||
private onReadyNext?: (data:ImageKnifeData|number|undefined) => void = undefined
|
||||
private onReadyNextData:ImageKnifeData|number|undefined = undefined
|
||||
|
||||
private detachFromLayout:DetachFromLayout;
|
||||
private detachFromLayout:DetachFromLayout|undefined = undefined;
|
||||
|
||||
build() {
|
||||
Canvas(this.context)
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.onAreaChange((oldValue: Area, newValue: Area) => {
|
||||
if(newValue != undefined && newValue.width != undefined && newValue.height != undefined) {
|
||||
this.currentWidth = newValue.width as number
|
||||
this.currentHeight = newValue.height as number
|
||||
if (this.currentWidth <= 0 || this.currentHeight <= 0) {
|
||||
|
@ -103,6 +104,9 @@ export struct ImageKnifeComponent {
|
|||
this.imageKnifeExecute()
|
||||
}
|
||||
}
|
||||
}else{
|
||||
LogUtil.log('ImageKnifeComponent onAreaChange Error newValue is undefined')
|
||||
}
|
||||
})
|
||||
.onReady(() => {
|
||||
this.canvasHasReady = true;
|
||||
|
@ -587,7 +591,7 @@ export struct ImageKnifeComponent {
|
|||
|
||||
aboutToDisappear() {
|
||||
LogUtil.log('ImageKnifeComponent aboutToDisappear happened!')
|
||||
if(this.detachFromLayout){
|
||||
if(this.detachFromLayout != undefined){
|
||||
this.detachFromLayout.detach();
|
||||
}
|
||||
|
||||
|
|
|
@ -84,4 +84,45 @@ export class ImageKnifeData {
|
|||
isResource(): boolean {
|
||||
return ImageKnifeType.RESOURCE == this.imageKnifeType;
|
||||
}
|
||||
|
||||
release(){
|
||||
if(this.isPixelMap()){
|
||||
if(this.drawPixelMap != undefined && this.drawPixelMap.imagePixelMap != undefined){
|
||||
this.drawPixelMap.imagePixelMap.release()
|
||||
.then(()=>{
|
||||
if(this.drawPixelMap != undefined && this.drawPixelMap.imagePixelMap !=undefined){
|
||||
this.drawPixelMap.imagePixelMap = undefined;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if(this.isGIFFrame()){
|
||||
if(this.drawGIFFrame != undefined){
|
||||
let gifFrames = this.drawGIFFrame.imageGIFFrames;
|
||||
if(gifFrames != undefined){
|
||||
for (let i = 0; i < gifFrames.length; i++) {
|
||||
let tempFrame = gifFrames[i];
|
||||
if(tempFrame.drawPixelMap != undefined){
|
||||
tempFrame.drawPixelMap.release()
|
||||
}
|
||||
}
|
||||
this.drawGIFFrame.imageGIFFrames = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.isString()){
|
||||
if(this.drawString != undefined && this.drawString.imageString!=undefined){
|
||||
this.drawString.imageString = undefined
|
||||
}
|
||||
}
|
||||
|
||||
if(this.isResource()){
|
||||
if(this.drawResource != undefined && this.drawResource.imageResource != undefined){
|
||||
this.drawResource.imageResource = undefined
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -140,7 +140,7 @@ export class RequestOption {
|
|||
|
||||
generateUUID(): string {
|
||||
let d = new Date().getTime();
|
||||
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( new RegExp("[xy]","g"), (c) => {
|
||||
const r = (d + Math.random() * 16) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||
|
|
|
@ -98,10 +98,11 @@ export class Engine {
|
|||
}
|
||||
imageResource.createPixelMap(options)
|
||||
.then(bitmap => {
|
||||
|
||||
imageResource.release()
|
||||
})
|
||||
.catch((error: BusinessError) => {
|
||||
this.mCompressListener.onError("ptah createPixelMap fail,because error:" + JSON.stringify(error as BusinessError))
|
||||
imageResource.release()
|
||||
})
|
||||
|
||||
|
||||
|
@ -173,11 +174,13 @@ export class Engine {
|
|||
if (this.mCompressListener) {
|
||||
this.mCompressListener.onSuccess(bitmap, path);
|
||||
}
|
||||
imageRes.release()
|
||||
})
|
||||
.catch((error:BusinessError) => {
|
||||
if (this.mCompressListener) {
|
||||
this.mCompressListener.onError("buffer generated pixelMap fail,because error:" + JSON.stringify(error as BusinessError))
|
||||
}
|
||||
imageRes.release()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,10 @@ export class RecourseProvider extends CompressAdapter {
|
|||
.then(data => {
|
||||
let buffer = this.uint8ArrayToBuffer(data);
|
||||
let fileTypeUtil = new FileTypeUtil()
|
||||
this._mPixelMapHeader = fileTypeUtil.getFileType(buffer);
|
||||
let fileType = fileTypeUtil.getFileType(buffer);
|
||||
if(fileType != null) {
|
||||
this._mPixelMapHeader = fileType;
|
||||
}
|
||||
callback.compressDataListener(buffer);
|
||||
})
|
||||
.catch((err: BusinessError) => {
|
||||
|
|
|
@ -66,9 +66,11 @@ export namespace Crop {
|
|||
} else {
|
||||
func?.cropCallback("", data);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
func?.cropCallback(e, null);
|
||||
imageSource.release()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -893,6 +893,7 @@ export class Options {
|
|||
if (readyCrop) {
|
||||
readyCrop();
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
|
||||
});
|
||||
|
|
|
@ -53,8 +53,10 @@ export class ErrorHolderManager<T> {
|
|||
if (typeof res.id != 'undefined' && typeof res.id != 'undefined') {
|
||||
let resourceFetch = new ParseResClient();
|
||||
let suc = (arraybuffer:ArrayBuffer) => {
|
||||
let fileTypeUtil:FileTypeUtil = new FileTypeUtil();
|
||||
let typeValue:string = fileTypeUtil.getFileType(arraybuffer);
|
||||
let fileTypeUtil: FileTypeUtil = new FileTypeUtil();
|
||||
|
||||
let typeValue: string | null = fileTypeUtil.getFileType(arraybuffer);
|
||||
if (typeValue != null) {
|
||||
switch (typeValue) {
|
||||
case SupportFormat.svg:
|
||||
this.svgProcess(onComplete, onError, arraybuffer, typeValue)
|
||||
|
@ -71,6 +73,9 @@ export class ErrorHolderManager<T> {
|
|||
onError("ErrorHolderManager 文件类型不支持")
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
onError("ErrorHolderManager 文件类型为null,请检查数据源arraybuffer")
|
||||
}
|
||||
}
|
||||
resourceFetch.loadResource(res, suc, onError)
|
||||
} else {
|
||||
|
|
|
@ -22,9 +22,11 @@ import { LoadDataShareFileClient } from './LoadDataShareFileClient'
|
|||
import loadRequest from '@ohos.request';
|
||||
import { ImageKnifeGlobal } from '../ImageKnifeGlobal'
|
||||
import common from '@ohos.app.ability.common'
|
||||
import { NetworkDownloadClient } from './NetworkDownloadClient'
|
||||
|
||||
// 数据加载器
|
||||
export class DownloadClient implements IDataFetch {
|
||||
private networkDownloadClient = new NetworkDownloadClient();
|
||||
private httpDownloadClient = new HttpDownloadClient();
|
||||
private localFileClient = new LoadLocalFileClient();
|
||||
private dataShareFileClient = new LoadDataShareFileClient();
|
||||
|
@ -42,6 +44,7 @@ export class DownloadClient implements IDataFetch {
|
|||
this.dataShareFileClient.loadData(request, onCompleteFunction, onErrorFunction)
|
||||
} else {
|
||||
// 网络下载
|
||||
// this.networkDownloadClient.loadData(request, onCompleteFunction, onErrorFunction)
|
||||
this.httpDownloadClient.loadData(request, onCompleteFunction, onErrorFunction)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ export class HttpDownloadClient implements IDataFetch {
|
|||
loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) {
|
||||
try {
|
||||
let httpRequest = http.createHttp()
|
||||
let arrayBuffers = new Array();
|
||||
let arrayBuffers = new Array<ArrayBuffer>();
|
||||
httpRequest.on('headersReceive', (header: Object) => {
|
||||
// 跟服务器连接成功准备下载
|
||||
if (request.progressFunc) {
|
||||
|
@ -48,10 +48,12 @@ export class HttpDownloadClient implements IDataFetch {
|
|||
|
||||
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 (request.progressFunc) {
|
||||
request.progressFunc.asyncSuccess(percent)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
httpRequest.on('dataEnd', () => {
|
||||
|
@ -73,12 +75,7 @@ export class HttpDownloadClient implements IDataFetch {
|
|||
if (!err && data == 200) {
|
||||
|
||||
} else {
|
||||
httpRequest.off('headersReceive');
|
||||
httpRequest.off('dataReceive');
|
||||
httpRequest.off('dataReceiveProgress');
|
||||
httpRequest.off('dataEnd');
|
||||
httpRequest.destroy()
|
||||
onError('HttpDownloadClient err message =' + err.message)
|
||||
onError(`HttpDownloadClient has error, http code = ${data}`)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -433,7 +433,12 @@ export class RequestManager {
|
|||
// 步骤二: 文件名保存一份全局
|
||||
// 步骤三:查看文件是否支持 非支持类型直接返回
|
||||
let fileTypeUtil = new FileTypeUtil();
|
||||
let filetype = fileTypeUtil.getFileType(source);
|
||||
let filetype:string|null = fileTypeUtil.getFileType(source);
|
||||
if(filetype == null){
|
||||
onError("下载文件解析后类型为null,请检查数据源!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fileTypeUtil.isImage(source)) {
|
||||
onError("暂不支持 下载文件类型!类型=" + filetype);
|
||||
return;
|
||||
|
@ -473,11 +478,15 @@ export class RequestManager {
|
|||
if (this.options.transformations[0]) {
|
||||
// thumbnail 缩略图部分
|
||||
if (this.options.thumbSizeMultiplier) {
|
||||
if(filetype != null) {
|
||||
this.thumbnailProcess(source, filetype, onComplete, onError);
|
||||
}
|
||||
} else {
|
||||
this.options.transformations[0].transform(source, this.options, {asyncTransform: (error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
if (pixelMap) {
|
||||
if(filetype != null) {
|
||||
this.saveCacheAndDisk(pixelMap, filetype, onComplete, source);
|
||||
}
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
|
@ -495,14 +504,18 @@ export class RequestManager {
|
|||
this.mParseImageUtil.parseImageThumbnail(this.options.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||
setTimeout(() => {
|
||||
let success = (value: PixelMap) => {
|
||||
if(filetype != null) {
|
||||
this.saveCacheAndDisk(value, filetype, onComplete, source);
|
||||
}
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
}, this.options.thumbDelayTime)
|
||||
} else {
|
||||
let success = (value: PixelMap) => {
|
||||
if(filetype != null) {
|
||||
this.saveCacheAndDisk(value, filetype, onComplete, source);
|
||||
}
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,9 +74,11 @@ export class BlurTransformation implements BaseTransform<PixelMap> {
|
|||
} else {
|
||||
fastBlur.blur(data, this._mRadius, true, func);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
imageSource.release()
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
}})
|
||||
|
|
|
@ -76,7 +76,7 @@ export class BrightnessFilterTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
let data = await imageSource.createPixelMap(options);
|
||||
|
||||
imageSource.release()
|
||||
let bufferData = new ArrayBuffer(data.getPixelBytesNumber());
|
||||
await data.readPixelsToBuffer(bufferData);
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ export class ContrastFilterTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
|
||||
let data = await imageSource.createPixelMap(options);
|
||||
|
||||
imageSource.release()
|
||||
let bufferData = new ArrayBuffer(data.getPixelBytesNumber());
|
||||
await data.readPixelsToBuffer(bufferData);
|
||||
|
||||
|
|
|
@ -75,12 +75,14 @@ export class CropCircleTransformation implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then((p:PixelMap) => {
|
||||
this.transformCircle(p, func);
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + CropCircleTransformation.TAG + " transform e:" + e);
|
||||
if (func!=undefined) {
|
||||
func?.asyncTransform(Constants.PROJECT_TAG + CropCircleTransformation.TAG + "e" + e, null);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -93,12 +93,14 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
imageSource.createPixelMap(options)
|
||||
.then((pixelMap:PixelMap) => {
|
||||
this.transformPixelMap(pixelMap, outWith, outHeight, func);
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation e:" + e);
|
||||
if (func!=undefined) {
|
||||
func?.asyncTransform(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation e:" + e, null);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -73,11 +73,13 @@ export class CropSquareTransformation implements BaseTransform<PixelMap> {
|
|||
if (func != undefined) {
|
||||
func?.asyncTransform("", data);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
if (func != undefined) {
|
||||
func?.asyncTransform(Constants.PROJECT_TAG + ";CropSquareTransformation e:" + e, null);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
})
|
||||
.catch((error:BusinessError) => {
|
||||
|
|
|
@ -83,9 +83,11 @@ export class CropTransformation implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then((data:PixelMap) => {
|
||||
func?.asyncTransform("", data);
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
imageSource.release()
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
}})
|
||||
|
|
|
@ -68,7 +68,7 @@ export class GrayscaleTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
let data:PixelMap= await imageSource.createPixelMap(options);
|
||||
|
||||
imageSource.release()
|
||||
let bufferData = new ArrayBuffer(data.getPixelBytesNumber());
|
||||
let bufferNewData = new ArrayBuffer(data.getPixelBytesNumber());
|
||||
await data.readPixelsToBuffer(bufferData);
|
||||
|
|
|
@ -77,7 +77,7 @@ export class InvertFilterTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
|
||||
let data:PixelMap = await imageSource.createPixelMap(options);
|
||||
|
||||
imageSource.release()
|
||||
let bufferData = new ArrayBuffer(data.getPixelBytesNumber());
|
||||
await data.readPixelsToBuffer(bufferData);
|
||||
|
||||
|
|
|
@ -79,10 +79,12 @@ export class KuwaharaFilterTransform implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then((data) => {
|
||||
this.kuwahara(data, targetWidth, targetHeight, func);
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
func?.asyncTransform(e, null);
|
||||
imageSource.release()
|
||||
})
|
||||
}})
|
||||
}
|
||||
|
|
|
@ -79,9 +79,11 @@ export class MaskTransformation implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then(data => {
|
||||
this.openInternal(data, targetWidth, targetHeight, func)
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError )=> {
|
||||
func?.asyncTransform(e, null);
|
||||
imageSource.release()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -80,9 +80,11 @@ export class PixelationFilterTransformation implements BaseTransform<PixelMap> {
|
|||
} else {
|
||||
pixelUtils.pixel(data, this._mPixel, func);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
imageSource.release();
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
}})
|
||||
|
|
|
@ -70,9 +70,11 @@ export class RotateImageTransformation implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then((data) => {
|
||||
func?.asyncTransform("", data);
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
imageSource.release()
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
}})
|
||||
|
|
|
@ -113,8 +113,10 @@ export class RoundedCornersTransformation implements BaseTransform<PixelMap> {
|
|||
if (func != undefined && this.mTransform_pixelMap != undefined) {
|
||||
func?.asyncTransform("", this.mTransform_pixelMap);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((error:BusinessError) => {
|
||||
imageSource.release()
|
||||
LogUtil.log(Constants.PROJECT_TAG + "RoundedCornersTransformation error:" + error);
|
||||
});
|
||||
})
|
||||
|
|
|
@ -73,7 +73,7 @@ export class SepiaFilterTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
let data:PixelMap = await imageSource.createPixelMap(options);
|
||||
|
||||
imageSource.release();
|
||||
let bufferData = new ArrayBuffer(data.getPixelBytesNumber());
|
||||
await data.readPixelsToBuffer(bufferData);
|
||||
|
||||
|
|
|
@ -66,9 +66,11 @@ export class SketchFilterTransformation implements BaseTransform<PixelMap> {
|
|||
} else {
|
||||
CalculatePixelUtils.sketch(data, func);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
func?.asyncTransform(e, null);
|
||||
imageSource.release()
|
||||
})
|
||||
}})
|
||||
}
|
||||
|
|
|
@ -81,8 +81,10 @@ export class SwirlFilterTransformation implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then((data) => {
|
||||
this.swirl(data, this.radius, request, func);
|
||||
imageSource.release();
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
imageSource.release();
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
}})
|
||||
|
|
|
@ -83,9 +83,11 @@ export class ToonFilterTransform implements BaseTransform<PixelMap> {
|
|||
}
|
||||
imageSource.createPixelMap(options)
|
||||
.then((data) => {
|
||||
imageSource.release()
|
||||
this.toon(data, targetWidth, targetHeight, func);
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
imageSource.release()
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
|
|
|
@ -63,7 +63,9 @@ export class TransformUtils {
|
|||
editable: true,
|
||||
rotate: degreesToRotate
|
||||
}
|
||||
return imageSource.createPixelMap(options);
|
||||
let promise:Promise<PixelMap> = imageSource.createPixelMap(options);
|
||||
imageSource.release()
|
||||
return promise;
|
||||
}
|
||||
|
||||
static centerInside(buf: ArrayBuffer, outWidth: number, outHeihgt: number,
|
||||
|
@ -74,7 +76,9 @@ export class TransformUtils {
|
|||
let pw = p.size.width;
|
||||
let ph = p.size.height;
|
||||
if (pw <= outWidth && ph <= outHeihgt) {
|
||||
callback?.asyncTransform('', imageSource.createPixelMap());
|
||||
let promise:Promise<PixelMap> = imageSource.createPixelMap()
|
||||
imageSource.release()
|
||||
callback?.asyncTransform('', promise);
|
||||
} else {
|
||||
TransformUtils.fitCenter(buf, outWidth, outHeihgt, callback);
|
||||
}
|
||||
|
@ -112,7 +116,9 @@ export class TransformUtils {
|
|||
desiredSize: { width: targetWidth, height: targetHeight }
|
||||
}
|
||||
if (callback) {
|
||||
callback.asyncTransform('', imageSource.createPixelMap(options));
|
||||
let promise:Promise<PixelMap> = imageSource.createPixelMap(options);
|
||||
imageSource.release();
|
||||
callback.asyncTransform('', promise);
|
||||
}
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
|
|
|
@ -88,8 +88,10 @@ export class VignetteFilterTransform implements BaseTransform<PixelMap> {
|
|||
imageSource.createPixelMap(options)
|
||||
.then((data) => {
|
||||
this.vignette(data, targetWidth, targetHeight, func);
|
||||
imageSource.release();
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
imageSource.release()
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";error:" + e);
|
||||
func?.asyncTransform(e, null);
|
||||
})
|
||||
|
|
|
@ -57,16 +57,26 @@ export class FileTypeUtil {
|
|||
|
||||
getFileType(file: ArrayBuffer): string | null {
|
||||
const fileData = new Uint8Array(file);
|
||||
for (const fileType in this.fileSignatureMap) {
|
||||
let hasMatched = false;
|
||||
let matchedFileType = ''
|
||||
Object.keys(this.fileSignatureMap).map((fileType)=>{
|
||||
if(!hasMatched) {
|
||||
const bufferList = this.fileSignatureMap[fileType];
|
||||
for (let i = 0; i < bufferList.length; i++) {
|
||||
let signature = bufferList[i];
|
||||
if(this.matchesSignature(fileData,signature)){
|
||||
return fileType;
|
||||
if (this.matchesSignature(fileData, signature)) {
|
||||
hasMatched = true;
|
||||
matchedFileType = fileType;
|
||||
break
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// 由于map函数会输出所有的keys, 所以匹配之后不再需要执行任何逻辑
|
||||
}
|
||||
})
|
||||
if(hasMatched){
|
||||
return matchedFileType;
|
||||
}
|
||||
|
||||
return null; // 若无法识别文件类型,返回null
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ export class ParseImageUtil implements IParseImage<PixelMap> {
|
|||
} else {
|
||||
onCompleteFunction(pixelmap);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -132,63 +132,3 @@ export class EasyLinkedHashMap<K, V> {
|
|||
this.tail=null;
|
||||
}
|
||||
}
|
||||
|
||||
function testLinkedHashMap(){
|
||||
// 创建一个新的 LinkedHashMap 实例
|
||||
let linkedHashMap = new EasyLinkedHashMap<string, number>();
|
||||
|
||||
// 添加键值对,并验证插入是否正确
|
||||
linkedHashMap.put('key1', 1);
|
||||
linkedHashMap.put('key2', 2);
|
||||
linkedHashMap.put('key3', 3);
|
||||
|
||||
console.log('dodo '+linkedHashMap.get('key1')); // 1
|
||||
console.log('dodo '+linkedHashMap.get('key2')); // 2
|
||||
console.log('dodo '+linkedHashMap.get('key3')); // 3
|
||||
|
||||
// 验证键值对更新是否正确
|
||||
linkedHashMap.put('key2', 20);
|
||||
console.log('dodo '+linkedHashMap.get('key2')); // 20
|
||||
|
||||
// 验证移除键值对是否正确
|
||||
linkedHashMap.remove('key1');
|
||||
console.log('dodo '+linkedHashMap.get('key1')); // undefined
|
||||
console.log('dodo '+linkedHashMap.size()); // 2
|
||||
|
||||
// 添加更多键值对
|
||||
linkedHashMap.put('key4', 4);
|
||||
linkedHashMap.put('key5', 5);
|
||||
linkedHashMap.put('key6', 6);
|
||||
|
||||
console.log('dodo '+linkedHashMap.size()); // 5
|
||||
|
||||
// 验证访问顺序是否正确,最近访问的键值对应该在链表尾部
|
||||
console.log('dodo '+linkedHashMap.get('key2')); // 20
|
||||
console.log('dodo '+linkedHashMap.get('key3')); // 3
|
||||
console.log('dodo '+linkedHashMap.get('key4')); // 4
|
||||
|
||||
// 添加更多键值对,超出容量限制(假设容量限制为 5)
|
||||
linkedHashMap.put('key7', 7);
|
||||
linkedHashMap.put('key8', 8);
|
||||
linkedHashMap.put('key9', 9);
|
||||
|
||||
console.log('dodo '+linkedHashMap.size()); // 5
|
||||
console.log('dodo '+linkedHashMap.get('key1')); // undefined,因为已经超过容量限制,最早访问的键值对被移除
|
||||
|
||||
// 验证移除最近访问的键值对后,访问顺序是否正确
|
||||
linkedHashMap.remove('key4');
|
||||
console.log('dodo '+linkedHashMap.get('key4')); // undefined
|
||||
console.log('dodo '+linkedHashMap.get('key2')); // 20
|
||||
console.log('dodo '+linkedHashMap.get('key3')); // 3
|
||||
|
||||
// 清空 LinkedHashMap
|
||||
linkedHashMap.remove('key2');
|
||||
linkedHashMap.remove('key3');
|
||||
linkedHashMap.remove('key5');
|
||||
linkedHashMap.remove('key6');
|
||||
linkedHashMap.remove('key7');
|
||||
linkedHashMap.remove('key8');
|
||||
linkedHashMap.remove('key9');
|
||||
|
||||
console.log('dodo '+linkedHashMap.size()); // 0
|
||||
}
|
|
@ -14,11 +14,7 @@
|
|||
*/
|
||||
import { IParseGif } from './IParseGif'
|
||||
import { Dims, GIFFrame } from './GIFFrame'
|
||||
import { LoadType } from '../../../../../../../GifWorker'
|
||||
import { parseBufferToFrame } from './parse/GIFParse'
|
||||
import { LogUtil } from '../../utils/LogUtil'
|
||||
import image from '@ohos.multimedia.image'
|
||||
import { ImageKnifeGlobal } from '../../ImageKnifeGlobal'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import worker, { ErrorEvent, MessageEvents } from '@ohos.worker';
|
||||
|
||||
|
@ -35,143 +31,49 @@ export interface gifBackData{
|
|||
transparentIndex:number[]
|
||||
}
|
||||
export class GIFParseImpl implements IParseGif {
|
||||
//
|
||||
parseGifs(imageinfo: ArrayBuffer, callback: (data?:GIFFrame[], err?:BusinessError|string) => void, worker?:worker.ThreadWorker,runMainThread?:boolean) {
|
||||
let resolveWorker = worker;
|
||||
LogUtil.log('parseGifs resolveWorker1 is null =' + (resolveWorker == null))
|
||||
if (!resolveWorker && ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
||||
resolveWorker = ImageKnifeGlobal.getInstance().getImageKnife()?.getGifWorker();
|
||||
// 硬解码流程
|
||||
let imageSource = image.createImageSource(imageinfo);
|
||||
let decodeOpts: image.DecodingOptions = {
|
||||
sampleSize: 1,
|
||||
editable: true,
|
||||
rotate: 0
|
||||
}
|
||||
LogUtil.log('parseGifs resolveWorker2 is null =' + (resolveWorker == null))
|
||||
|
||||
if (!!resolveWorker && !runMainThread) {
|
||||
LogUtil.log('parseGifs in worker thread!')
|
||||
let copyBuffer = imageinfo.slice(0);
|
||||
this.useWorkerParse(resolveWorker, copyBuffer, (data, err) => {
|
||||
if (err) {
|
||||
callback(undefined, err)
|
||||
} else {
|
||||
if (data != undefined) {
|
||||
this.createPixelMapAll(data).then((pixelmaps) => {
|
||||
if (pixelmaps.length == data.length) {
|
||||
for (let i = 0;i < data.length; i++) {
|
||||
let frame = data[i];
|
||||
frame['drawPixelMap'] = pixelmaps[i];
|
||||
frame['patch'] = undefined;
|
||||
}
|
||||
callback(data, undefined)
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
callback(undefined, err)
|
||||
})
|
||||
}else{
|
||||
callback(undefined, 'GIF Parse Error callback data is undefined')
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
LogUtil.log('parseGifs in main thread!')
|
||||
let frames = parseBufferToFrame(imageinfo)
|
||||
LogUtil.log('frames length =' + frames.length)
|
||||
this.createPixelMapAll(frames).then((pixelmaps) => {
|
||||
if (pixelmaps.length == frames.length) {
|
||||
for (let i = 0;i < frames.length; i++) {
|
||||
let frame = frames[i];
|
||||
frame['drawPixelMap'] = pixelmaps[i];
|
||||
frame['patch'] = undefined;
|
||||
}
|
||||
LogUtil.log('parseGifs in main thread! callback is done!')
|
||||
callback(frames, undefined)
|
||||
}
|
||||
}).catch((err:BusinessError) => {
|
||||
LogUtil.log('parseGifs in main thread! err =' + err)
|
||||
callback(undefined, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private createPixelMapAll(frames:GIFFrame[]): Promise<PixelMap[]> {
|
||||
let promises:Promise<PixelMap>[] = new Array();
|
||||
let filterCriteria = (item:GIFFrame) => {
|
||||
if (!item['drawPixelMap']) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
frames.filter(filterCriteria, frames).flatMap<void,undefined>((frame:GIFFrame) => {
|
||||
if(frame.patch != undefined) {
|
||||
promises.push(image.createPixelMap(frame.patch.buffer, {
|
||||
'size': {
|
||||
'height': frame.dims.height as number,
|
||||
'width': frame.dims.width as number
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
return Promise.all<PixelMap>(promises)
|
||||
}
|
||||
|
||||
private useWorkerParse(worker:worker.ThreadWorker, buffer: ArrayBuffer, callback: (data?:GIFFrame[], err?:BusinessError|string) => void) {
|
||||
|
||||
worker.onerror = (err:ErrorEvent)=>{
|
||||
callback(undefined, err.message)
|
||||
}
|
||||
|
||||
worker.onmessageerror = (event: MessageEvents) => {
|
||||
callback(undefined, event.type)
|
||||
}
|
||||
|
||||
worker.onexit = ()=> {
|
||||
LogUtil.log('gifWork worker.onexit!')
|
||||
}
|
||||
|
||||
worker.onmessage = (e: MessageEvents) => {
|
||||
let data:Record<string,Object> = e.data;
|
||||
switch (data.type as string) {
|
||||
case LoadType.loadBufferByWorker:
|
||||
let pages:gifBackData = (data.data as gifBackData);
|
||||
if (this.gifDecodeCorrect(pages)) {
|
||||
let images = this.recDecodedData(pages);
|
||||
callback(images, undefined)
|
||||
} else {
|
||||
callback(undefined, 'GIF Worker Decoder Data Is Error!')
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let obj:senderData = { type: LoadType.loadBufferByWorker, data: buffer }
|
||||
worker.postMessage(obj, [buffer])
|
||||
|
||||
}
|
||||
|
||||
private gifDecodeCorrect(frames:gifBackData) {
|
||||
if (
|
||||
(frames.patch.length == frames.dims.length) &&
|
||||
(frames.patch.length == frames.delay.length) &&
|
||||
(frames.patch.length == frames.disposalType.length) &&
|
||||
(frames.patch.length == frames.patch.length) &&
|
||||
(frames.patch.length == frames.transparentIndex.length)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 子线程数据回传处理
|
||||
private recDecodedData(pages:gifBackData): GIFFrame[] {
|
||||
let images:GIFFrame[] = new Array()
|
||||
for (let i = 0; i < pages.patch.length; i++) {
|
||||
let data:GIFFrame[] = [];
|
||||
imageSource.createPixelMapList(decodeOpts).then((pixelList: Array<PixelMap>) => {
|
||||
//sdk的api接口发生变更:从.getDelayTime() 变为.getDelayTimeList()
|
||||
imageSource.getDelayTimeList().then(delayTimes => {
|
||||
if (pixelList.length > 0) {
|
||||
let pixelmap1 = pixelList[0];
|
||||
pixelmap1.getImageInfo().then(imageInfo => {
|
||||
for (let i = 0; i < pixelList.length; i++) {
|
||||
let frame = new GIFFrame();
|
||||
frame['dims'] = pages.dims[i]
|
||||
frame['delay'] = pages.delay[i]
|
||||
frame['disposalType'] = pages.disposalType[i]
|
||||
let uint8ClampedArray = new Uint8ClampedArray(pages.patch[i])
|
||||
frame['patch'] = uint8ClampedArray
|
||||
frame['transparentIndex'] = pages.transparentIndex[i]
|
||||
images.push(frame)
|
||||
frame.drawPixelMap = pixelList[i];
|
||||
frame.dims = { width: imageInfo.size.width, height: imageInfo.size.height, top: 0, left: 0 }
|
||||
if (i < delayTimes.length) {
|
||||
frame.delay = delayTimes[i];
|
||||
} else {
|
||||
frame.delay = delayTimes[delayTimes.length - 1]
|
||||
}
|
||||
return images;
|
||||
data.push(frame)
|
||||
}
|
||||
callback(data,undefined)
|
||||
imageSource.release();
|
||||
}).catch((err: string) => {
|
||||
imageSource.release();
|
||||
callback(undefined,err)
|
||||
})
|
||||
}
|
||||
}).catch((err: string) => {
|
||||
imageSource.release();
|
||||
callback(undefined,err)
|
||||
})
|
||||
}).catch((err: string) => {
|
||||
imageSource.release();
|
||||
callback(undefined,err)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,6 @@
|
|||
"name": "imageknife",
|
||||
"description": "example description",
|
||||
"repository": {},
|
||||
"version": "2.1.1-rc.0",
|
||||
"version": "2.1.1-rc.3",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue