master分支代码合并taskpool分支代码
Signed-off-by: zenggaofeng <zenggaofeng2@h-partners.com>
This commit is contained in:
commit
a3ce29f8d2
|
@ -1,5 +1,9 @@
|
|||
## 2.1.2-rc.11
|
||||
- 修复设置磁盘容量最大值出现闪退
|
||||
- 修复概率出现jscrash问题
|
||||
- 修复进度条问题
|
||||
- 修复单帧gif图片加载失败
|
||||
- removeRunning删除running队列log设置开关
|
||||
|
||||
## 2.1.2-rc.10
|
||||
- 修复部分gif图片识别成静态图
|
||||
|
|
|
@ -109,18 +109,13 @@ struct basicTestFileIOPage {
|
|||
this.imageHint2 = 'appFilePath未取到值,请按顺序从上往下,从左往右依次测试'
|
||||
return
|
||||
}
|
||||
try {
|
||||
let filePath1 = this.appFilePath + '/Folder1/jpgSample.gif';
|
||||
let filePath2 = this.appFilePath + '/Folder2/jpgSample.gif';
|
||||
FileUtils.getInstance().createFolder(this.appFilePath + '/Folder1')
|
||||
FileUtils.getInstance().createFolder(this.appFilePath + '/Folder2')
|
||||
FileUtils.getInstance().copyFile(filePath1, filePath2);
|
||||
this.imageFile = 'file://' + this.appFilePath + '/Folder2/jpgSample.gif'
|
||||
console.log('Folder2 imaeFile =' + this.imageFile)
|
||||
} catch (e) {
|
||||
console.log('appFilePath未取到值,请按顺序从上往下,从左往右依次测试:'+JSON.stringify(e))
|
||||
}
|
||||
|
||||
let filePath1 = this.appFilePath + '/Folder1/jpgSample.gif';
|
||||
let filePath2 = this.appFilePath + '/Folder2/jpgSample.gif';
|
||||
FileUtils.getInstance().createFolder(this.appFilePath + '/Folder1')
|
||||
FileUtils.getInstance().createFolder(this.appFilePath + '/Folder2')
|
||||
FileUtils.getInstance().copyFile(filePath1, filePath2);
|
||||
this.imageFile = 'file://' + this.appFilePath + '/Folder2/jpgSample.gif'
|
||||
console.log('Folder2 imaeFile =' + this.imageFile)
|
||||
})
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Button('显示空PixelMap')
|
||||
|
|
|
@ -290,6 +290,10 @@ struct IndexFunctionDemo {
|
|||
.onClick(() => {
|
||||
router.pushUrl({ url: "pages/testManyNetImageLoadWithPage" });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
Button("多线程加载大量网络图片加载速度")
|
||||
.onClick(() => {
|
||||
router.pushUrl({ url: "pages/testManyNetImageLoadWithPage2" });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
Button("测试多张gif加载位置")
|
||||
.onClick(() => {
|
||||
router.pushUrl({ url: "pages/testManyGifLoadWithPage" });
|
||||
|
|
|
@ -18,9 +18,8 @@ import {ImageKnifeGlobal} from '@ohos/libraryimageknife'
|
|||
import {RotateImageTransformation} from '@ohos/libraryimageknife'
|
||||
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 {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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, NONE, DiskStrategy } from "@ohos/libraryimageknife"
|
||||
import { Material } from './model/Material';
|
||||
import { TestDataSource } from './model/TestDataSource';
|
||||
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct TestManyNetImageLoadWithPage2 {
|
||||
private data: TestDataSource = new TestDataSource();
|
||||
private setting: DiskStrategy = new NONE();
|
||||
private scroller: Scroller = new Scroller()
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column() {
|
||||
Grid(this.scroller) {
|
||||
LazyForEach(this.data, (item: Material, index) => {
|
||||
GridItem() {
|
||||
Stack({ alignContent: Alignment.BottomEnd }) {
|
||||
ImageKnifeComponent({
|
||||
imageKnifeOption: {
|
||||
loadSrc: item.thumbnail,
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
mainScaleType: ScaleType.CENTER_CROP,
|
||||
placeholderScaleType: ScaleType.CENTER_CROP,
|
||||
isCacheable: false,
|
||||
strategy: this.setting
|
||||
}
|
||||
}).width('100%').height('100%')
|
||||
Text(index + "." + item.name)
|
||||
.fontSize(10)
|
||||
.maxLines(1)
|
||||
.fontColor(Color.White)
|
||||
.textAlign(TextAlign.Center)
|
||||
.layoutWeight(1)
|
||||
.width('100%')
|
||||
.backgroundColor(Color.Orange)
|
||||
}
|
||||
}.width('45%').height(200)
|
||||
}, (item: Material) => item.material_id)
|
||||
}
|
||||
.columnsTemplate('1fr 1fr')
|
||||
.columnsGap(8)
|
||||
.rowsGap(10)
|
||||
.width('100%')
|
||||
.cachedCount(1)
|
||||
.height('100%')
|
||||
}.margin({ top: 5 })
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@
|
|||
"pages/hspCacheTestPage",
|
||||
"pages/multiHspTestPage",
|
||||
"pages/testManyNetImageLoadWithPage",
|
||||
"pages/testManyNetImageLoadWithPage2",
|
||||
"pages/testManyGifLoadWithPage",
|
||||
"pages/testImageAntiAliasingWithPage",
|
||||
"pages/testImageKnifeRouter1",
|
||||
|
|
|
@ -18,10 +18,12 @@ import LogUtilTest from './logutil.test'
|
|||
import Transform from './transfrom.test'
|
||||
import RequestOptionTest from './requestoption.test'
|
||||
import ImageKnifeTest from './imageknife.test'
|
||||
import DiskLruCacheTest from './diskLruCache.test'
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest()
|
||||
lruCacheTest()
|
||||
DiskLruCacheTest()
|
||||
LogUtilTest()
|
||||
Transform()
|
||||
RequestOptionTest()
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
|
||||
import { DiskLruCache, DiskCacheEntry } from '@ohos/imageknife'
|
||||
import { common } from '@kit.AbilityKit';
|
||||
import fs from '@ohos.file.fs';
|
||||
import { GlobalContext } from '../testability/GlobalContext'
|
||||
|
||||
const BASE_COUNT: number = 2000;
|
||||
|
||||
export default function DiskLruCacheTest() {
|
||||
|
||||
describe('DiskLruCacheTest', () => {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
beforeAll(() => {
|
||||
//ImageKnife.with(this.context.createModuleContext("entry_test"));
|
||||
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
beforeEach(() => {
|
||||
|
||||
// Presets an action, which is performed before each unit test case starts.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
afterEach(() => {
|
||||
// Presets a clear action, which is performed after each unit test case ends.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
afterAll(() => {
|
||||
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
it('testSetCahe', 0, () => {
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let disLruCache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
let startTime = new Date().getTime();
|
||||
disLruCache.set('test', "Hello World Simple Example.");
|
||||
disLruCache.set('testABC', "Hello World ABC");
|
||||
disLruCache.set('testDE', "Hello World Simple DE");
|
||||
expect(String.fromCharCode(...new Uint8Array(disLruCache.get('test') as ArrayBufferLike)) == "Hello World Simple Example.")
|
||||
.assertTrue()
|
||||
expect(String.fromCharCode(...new Uint8Array(disLruCache.get('testABC') as ArrayBufferLike)) == "Hello World ABC")
|
||||
.assertTrue()
|
||||
expect(String.fromCharCode(...new Uint8Array(disLruCache.get('testDE') as ArrayBufferLike)) == "Hello World Simple DE")
|
||||
.assertTrue()
|
||||
let str: string = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
||||
for (let index = 0; index < 100; index++) {
|
||||
str += index;
|
||||
disLruCache.set('test' + index, str);
|
||||
}
|
||||
expect(disLruCache.getSize() <= 1024).assertTrue()
|
||||
endTime(startTime, 'testSetCahe');
|
||||
disLruCache.cleanCacheData();
|
||||
|
||||
})
|
||||
it('testGetCacheAsync', 1, () => {
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let filesDir: object | undefined = GlobalContext.getInstance().getObject("filesDir");
|
||||
let cache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
let startTime = new Date().getTime();
|
||||
let path = filesDir + '/testFile.txt';
|
||||
let file = fs.openSync(path, 0o102);
|
||||
fs.writeSync(file.fd, "hello, world!");
|
||||
let length = fs.statSync(path).size;
|
||||
let dataArr = new ArrayBuffer(length);
|
||||
fs.readSync(file.fd, dataArr);
|
||||
cache.set('testFile', dataArr);
|
||||
expect(cache.get('testFile')?.byteLength == 13).assertTrue()
|
||||
endTime(startTime, 'testGetCacheAsync');
|
||||
cache.cleanCacheData();
|
||||
})
|
||||
it('testDeleteCacheDataByKey', 2, () => {
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let cache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
let startTime = new Date().getTime();
|
||||
cache.set('test', "Hello World Simple Example.");
|
||||
cache.set('testABC', "Hello World ABC");
|
||||
expect(String.fromCharCode(...new Uint8Array(cache.get('test') as ArrayBufferLike)))
|
||||
.assertEqual("Hello World Simple Example.");
|
||||
expect(String.fromCharCode(...new Uint8Array(cache.get('testABC') as ArrayBufferLike)))
|
||||
.assertEqual("Hello World ABC");
|
||||
cache.deleteCacheDataByKey('test');
|
||||
cache.deleteCacheDataByKey('testABC');
|
||||
expect(String.fromCharCode(...new Uint8Array(cache.get('test') as ArrayBufferLike))).assertEqual('');
|
||||
expect(String.fromCharCode(...new Uint8Array(cache.get('testABC') as ArrayBufferLike))).assertEqual('');
|
||||
endTime(startTime, 'testDeleteCacheDataByKey');
|
||||
cache.cleanCacheData();
|
||||
})
|
||||
it('testGetPath', 3, () => {
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let cache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
let startTime = new Date().getTime();
|
||||
cache.set('test', "Hello World Simple Example.");
|
||||
let path: string = cache.getFileToPath('test');
|
||||
expect(String.fromCharCode(...new Uint8Array(cache.get('test') as ArrayBufferLike)) == "Hello World Simple Example.")
|
||||
.assertTrue()
|
||||
expect(cache.getFileToPath('test') == path).assertTrue()
|
||||
expect(cache.getPath() + cache.getCacheMap().getFirstKey() == path).assertTrue()
|
||||
endTime(startTime, 'testGetPath');
|
||||
cache.cleanCacheData();
|
||||
})
|
||||
it('testGetCacheMap', 6, () => {
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let cache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
let startTime = new Date().getTime();
|
||||
cache.set('test', "Hello World Simple Example.");
|
||||
expect(cache.getCacheMap().getFirstKey() == '098f6bcd4621d373cade4e832627b4f6').assertTrue()
|
||||
expect(cache.getCacheMap().hasKey('098f6bcd4621d373cade4e832627b4f6') == true).assertTrue()
|
||||
endTime(startTime, 'testGetCacheMap');
|
||||
cache.cleanCacheData();
|
||||
|
||||
})
|
||||
|
||||
it('testGetSize', 7, () => {
|
||||
let context: object | undefined = GlobalContext.getInstance().getObject("hapContext");
|
||||
let cache: DiskLruCache = DiskLruCache.create(context as common.UIAbilityContext, 1024);
|
||||
let startTime = new Date().getTime();
|
||||
cache.set('test', "Hello World Simple Example.");
|
||||
expect(String.fromCharCode(...new Uint8Array(cache.get('test') as ArrayBufferLike)) == "Hello World Simple Example.")
|
||||
.assertTrue()
|
||||
expect(cache.getSize() == 27).assertTrue()
|
||||
endTime(startTime, 'testGetSize');
|
||||
cache.cleanCacheData();
|
||||
|
||||
})
|
||||
|
||||
it('testDiskCacheEntry', 8, () => {
|
||||
let startTime = new Date().getTime();
|
||||
let dentry = new DiskCacheEntry('test', 30 * 1024 * 1024)
|
||||
expect(dentry.getKey() == 'test').assertTrue()
|
||||
dentry.setKey('newtest')
|
||||
expect(dentry.getKey() == 'newtest').assertTrue()
|
||||
expect(dentry.getLength() == 30 * 1024 * 1024).assertTrue()
|
||||
dentry.setLength(12 * 1024 * 1024)
|
||||
expect(dentry.getLength() == 12 * 1024 * 1024).assertTrue()
|
||||
expect(dentry.toString() == dentry.getKey() + ' - ' + dentry.getLength()).assertTrue()
|
||||
endTime(startTime, 'testDiskCacheEntry');
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function endTime(startTime: number, tag: string) {
|
||||
let endTime: number = new Date().getTime();
|
||||
let averageTime = ((endTime - startTime) * 1000 / BASE_COUNT)
|
||||
console.info(tag + " startTime: " + endTime)
|
||||
console.info(tag + " endTime: " + endTime)
|
||||
console.log(tag + " averageTime: " + averageTime + "μs");
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export class GlobalContext {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
private static instance: GlobalContext;
|
||||
private _objects = new Map<string, Object>();
|
||||
|
||||
public static getInstance(): GlobalContext {
|
||||
if (!GlobalContext.instance) {
|
||||
GlobalContext.instance = new GlobalContext();
|
||||
}
|
||||
return GlobalContext.instance;
|
||||
}
|
||||
|
||||
getObject(value: string): Object | undefined {
|
||||
return this._objects.get(value);
|
||||
}
|
||||
|
||||
setObject(key: string, objectClass: Object): void {
|
||||
this._objects.set(key, objectClass);
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import {ImageKnife,ImageKnifeDrawFactory,ImageKnifeGlobal} from '@ohos/libraryim
|
|||
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
|
||||
import Want from '@ohos.app.ability.Want';
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import {GlobalContext } from './GlobalContext'
|
||||
export default class TestAbility extends UIAbility {
|
||||
onCreate(want: Want, param: AbilityConstant.LaunchParam) {
|
||||
|
||||
|
@ -33,6 +34,8 @@ export default class TestAbility extends UIAbility {
|
|||
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
|
||||
// 初始化xts的ImageKnife
|
||||
ImageKnife.with(this.context.createModuleContext("entry_test"));
|
||||
GlobalContext.getInstance().setObject("hapContext",this.context.createModuleContext("entry_test"));
|
||||
GlobalContext.getInstance().setObject("filesDir",this.context.createModuleContext("entry_test").filesDir);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
export { FileUtils } from './src/main/ets/components/cache/FileUtils'
|
||||
export { Base64 } from './src/main/ets/components/cache/Base64'
|
||||
export { LruCache } from './src/main/ets/components/cache/LruCache'
|
||||
export { DiskLruCache } from './src/main/ets/components/cache/DiskLruCache'
|
||||
export { DiskCacheEntry } from './src/main/ets/components/cache/DiskCacheEntry'
|
||||
export { DiskStrategy } from './src/main/ets/components/cache/diskstrategy/DiskStrategy'
|
||||
export { ALL } from './src/main/ets/components/cache/diskstrategy/enum/ALL'
|
||||
export { AUTOMATIC } from './src/main/ets/components/cache/diskstrategy/enum/AUTOMATIC'
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
"version": "2.1.2-rc.11",
|
||||
"dependencies": {
|
||||
"pako": "^2.1.0",
|
||||
"@ohos/disklrucache": "^2.0.2-rc.0",
|
||||
"@ohos/gpu_transform": "^1.0.0"
|
||||
},
|
||||
"tags": [
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
export class DiskCacheEntry {
|
||||
// 缓存的key
|
||||
key: string = ''
|
||||
|
||||
// 缓存文件大小
|
||||
length: number = 0
|
||||
|
||||
constructor(key: string, length?: number) {
|
||||
this.key = key
|
||||
this.length = length as number
|
||||
}
|
||||
|
||||
setKey(key: string) {
|
||||
this.key = key
|
||||
}
|
||||
|
||||
getKey(): string {
|
||||
return this.key
|
||||
}
|
||||
|
||||
setLength(length: number) {
|
||||
this.length = length
|
||||
}
|
||||
|
||||
getLength(): number {
|
||||
return this.length
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.key + ' - ' + this.length
|
||||
}
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
* 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 fileio from '@ohos.fileio'
|
||||
import { CustomMap } from './CustomMap'
|
||||
import { FileUtils } from './FileUtils'
|
||||
import { FileReader } from './FileReader'
|
||||
import { DiskCacheEntry } from './DiskCacheEntry'
|
||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'
|
||||
import { Context } from '@ohos.abilityAccessCtrl'
|
||||
import { common } from '@kit.AbilityKit'
|
||||
|
||||
export class DiskLruCache {
|
||||
// 默认缓存数据最大值
|
||||
private static readonly DEFAULT_MAX_SIZE: number = 300 * 1024 * 1024
|
||||
// 默认缓存文件名
|
||||
private static readonly DEFAULT_NAME: string = 'diskLruCache'
|
||||
// 缓存journal文件名称
|
||||
private static readonly journal: string = 'journal'
|
||||
// 缓存journal备份文件名称
|
||||
private static readonly journalTemp: string = 'journal_temp'
|
||||
// 备份文件save标识符
|
||||
private static readonly SAVE: string = 'save'
|
||||
// 备份文件read标识符
|
||||
private static readonly READ: string = 'read'
|
||||
// 备份文件remove标识符
|
||||
private static readonly REMOVE: string = 'remove'
|
||||
// 缓存文件路径地址
|
||||
private path: string = ''
|
||||
// 缓存journal文件路径
|
||||
private journalPath: string = ''
|
||||
// 缓存journal备份文件路径
|
||||
private journalPathTemp: string = ''
|
||||
// 缓存数据最大值
|
||||
private maxSize: number = DiskLruCache.DEFAULT_MAX_SIZE
|
||||
// 当前缓存数据值
|
||||
private size: number = 0
|
||||
// 缓存数据集合
|
||||
private cacheMap: CustomMap<string, DiskCacheEntry> = new CustomMap<string, DiskCacheEntry>()
|
||||
|
||||
constructor(path: string, maxSize: number) {
|
||||
this.path = path
|
||||
this.maxSize = maxSize
|
||||
this.journalPath = path + DiskLruCache.journal
|
||||
this.journalPathTemp = path + DiskLruCache.journalTemp
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开context获取的cache路径中的缓存,如果不存在缓存,则创建新缓存
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param maxSize 缓存数据最大值,默认值为300M
|
||||
*/
|
||||
public static create(context: common.UIAbilityContext, maxSize?: number): DiskLruCache {
|
||||
if (!!!context) {
|
||||
throw new Error('DiskLruCache create context is empty, checking the parameter');
|
||||
}
|
||||
if (!!!maxSize) {
|
||||
maxSize = DiskLruCache.DEFAULT_MAX_SIZE
|
||||
}
|
||||
if (maxSize <= 0) {
|
||||
throw new Error("DiskLruCache create maxSize <= 0, checking the parameter");
|
||||
}
|
||||
|
||||
// 使用默认应用在内部存储上的缓存路径,作为存储地址
|
||||
let path = context.cacheDir + FileUtils.SEPARATOR + DiskLruCache.DEFAULT_NAME
|
||||
if (!FileUtils.getInstance().existFolder(path)) {
|
||||
FileUtils.getInstance().createFolder(path)
|
||||
}
|
||||
if (path.endsWith(FileUtils.SEPARATOR)) {
|
||||
path = path
|
||||
} else {
|
||||
path = path + FileUtils.SEPARATOR
|
||||
}
|
||||
let journalPath = path + DiskLruCache.journal
|
||||
let journalPathTemp = path + DiskLruCache.journalTemp
|
||||
|
||||
// 判断日志文件是否存在,如果没有初始化创建
|
||||
if (FileUtils.getInstance().exist(journalPath)) {
|
||||
let stat = fileio.statSync(journalPath)
|
||||
if (stat.size > 0) {
|
||||
FileUtils.getInstance().createFile(journalPathTemp)
|
||||
FileUtils.getInstance().copyFile(journalPath, journalPathTemp)
|
||||
let diskLruCache: DiskLruCache = new DiskLruCache(path, maxSize)
|
||||
diskLruCache.readJournal(journalPathTemp)
|
||||
diskLruCache.resetJournalFile()
|
||||
return diskLruCache
|
||||
} else {
|
||||
return new DiskLruCache(path, maxSize)
|
||||
}
|
||||
} else {
|
||||
FileUtils.getInstance().createFile(journalPath)
|
||||
return new DiskLruCache(path, maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置disk缓存最大数据值
|
||||
*
|
||||
* @param max 缓存数据最大值
|
||||
*/
|
||||
setMaxSize(max: number) {
|
||||
if (max <= 0 || max > DiskLruCache.DEFAULT_MAX_SIZE) {
|
||||
throw new Error('setMaxSize error, checking the parameter');
|
||||
}
|
||||
this.maxSize = max
|
||||
this.trimToSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储disk缓存数据
|
||||
*
|
||||
* @param key 键值
|
||||
* @param content 文件内容
|
||||
*/
|
||||
set(key: string, content: ArrayBuffer | string) {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null, checking the parameter')
|
||||
}
|
||||
let fileSize = 0;
|
||||
if (content instanceof ArrayBuffer) {
|
||||
if (content == null || content.byteLength == 0) {
|
||||
throw new Error('content is null. checking the parameter')
|
||||
}
|
||||
fileSize = content.byteLength
|
||||
} else {
|
||||
if (!!!content) {
|
||||
throw new Error('content is null, checking the parameter')
|
||||
}
|
||||
fileSize = content.length;
|
||||
}
|
||||
if (this.fileSizeMoreThenMaxSize(fileSize)) {
|
||||
throw new Error('content must be less then DiskLruCache Size, checking the parameter')
|
||||
return
|
||||
}
|
||||
key = SparkMD5.hashBinary(key)
|
||||
this.size = this.size + fileSize
|
||||
this.putCacheMap(key, fileSize)
|
||||
FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF)
|
||||
this.trimToSize()
|
||||
let tempPath = this.path + key
|
||||
FileUtils.getInstance().writeNewFile(tempPath, content)
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步存储disk缓存数据
|
||||
*
|
||||
* @param key 键值
|
||||
* @param content 文件内容
|
||||
*/
|
||||
async setAsync(key: string, content: ArrayBuffer | string): Promise<void> {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null, checking the parameter')
|
||||
}
|
||||
let fileSize = 0;
|
||||
if (content instanceof ArrayBuffer) {
|
||||
if (content == null || content.byteLength == 0) {
|
||||
throw new Error('content is null. checking the parameter')
|
||||
}
|
||||
fileSize = content.byteLength
|
||||
} else {
|
||||
if (!!!content) {
|
||||
throw new Error('content is null, checking the parameter')
|
||||
}
|
||||
fileSize = content.length;
|
||||
}
|
||||
if (this.fileSizeMoreThenMaxSize(fileSize)) {
|
||||
throw new Error('content must be less then DiskLruCache Size, checking the parameter')
|
||||
return
|
||||
}
|
||||
key = SparkMD5.hashBinary(key)
|
||||
this.size = this.size + fileSize
|
||||
this.putCacheMap(key, fileSize)
|
||||
await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF)
|
||||
this.trimToSize()
|
||||
let tempPath = this.path + key
|
||||
await FileUtils.getInstance().writeNewFileAsync(tempPath, content)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取key缓存数据
|
||||
*
|
||||
* @param key key 键值
|
||||
*/
|
||||
get(key: string): ArrayBuffer | undefined {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null,checking the parameter');
|
||||
}
|
||||
key = SparkMD5.hashBinary(key)
|
||||
let path = this.path + key;
|
||||
if (FileUtils.getInstance().exist(path)) {
|
||||
let ab: ArrayBuffer = FileUtils.getInstance().readFile(path)
|
||||
this.putCacheMap(key, ab.byteLength)
|
||||
FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF)
|
||||
return ab
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步获取key缓存数据
|
||||
*
|
||||
* @param key 键值
|
||||
*/
|
||||
async getAsync(key: string): Promise<ArrayBuffer | undefined> {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null,checking the parameter');
|
||||
}
|
||||
key = SparkMD5.hashBinary(key)
|
||||
let path = this.path + key;
|
||||
if (FileUtils.getInstance().exist(path)) {
|
||||
let ab: ArrayBuffer = await FileUtils.getInstance().readFileAsync(path)
|
||||
this.putCacheMap(key, ab.byteLength)
|
||||
await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF)
|
||||
return ab
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取key缓存数据绝对路径
|
||||
*
|
||||
* @param key 键值
|
||||
*/
|
||||
getFileToPath(key: string): string {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null,checking the parameter');
|
||||
}
|
||||
key = SparkMD5.hashBinary(key);
|
||||
let path = this.path + key;
|
||||
if (FileUtils.getInstance().exist(path)) {
|
||||
FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF);
|
||||
return path
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步获取key缓存数据绝对路径
|
||||
*
|
||||
* @param key 键值
|
||||
*/
|
||||
async getFileToPathAsync(key: string): Promise<string> {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null,checking the parameter');
|
||||
}
|
||||
key = SparkMD5.hashBinary(key);
|
||||
let path = this.path + key;
|
||||
if (FileUtils.getInstance().exist(path)) {
|
||||
await FileUtils.getInstance().writeDataAsync(this.journalPath, DiskLruCache.READ + ' ' + key + FileReader.LF);
|
||||
return path
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存路径
|
||||
*/
|
||||
getPath(): string {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除key缓存数据
|
||||
*
|
||||
* @param key 键值
|
||||
*/
|
||||
deleteCacheDataByKey(key: string): DiskCacheEntry {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null,checking the parameter');
|
||||
}
|
||||
key = SparkMD5.hashBinary(key)
|
||||
let path = this.path + key;
|
||||
if (FileUtils.getInstance().exist(path)) {
|
||||
let ab = FileUtils.getInstance().readFile(path)
|
||||
this.size = this.size - ab.byteLength
|
||||
this.cacheMap.remove(key)
|
||||
FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.REMOVE + ' ' + key + FileReader.LF)
|
||||
FileUtils.getInstance().deleteFile(path)
|
||||
}
|
||||
return this.cacheMap.get(key) as DiskCacheEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
*遍历当前的磁盘缓存数据
|
||||
*
|
||||
* @param fn 遍历后方法回调
|
||||
*/
|
||||
foreachDiskLruCache(fn: Function) {
|
||||
this.cacheMap.each(fn())
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有disk缓存数据
|
||||
*/
|
||||
cleanCacheData() {
|
||||
this.cacheMap.each((value, key) => {
|
||||
FileUtils.getInstance().deleteFile(this.path + key)
|
||||
})
|
||||
FileUtils.getInstance().deleteFile(this.journalPath)
|
||||
this.cacheMap.clear()
|
||||
this.size = 0
|
||||
}
|
||||
|
||||
getCacheMap() {
|
||||
return this.cacheMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前DiskLruCache的size大小
|
||||
*/
|
||||
getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理journal文件数据
|
||||
*
|
||||
* @param line 日志行字符串
|
||||
*/
|
||||
private dealWithJournal(line: string) {
|
||||
let filePath = ''
|
||||
try {
|
||||
let lineData = line.split(' ')
|
||||
if (lineData.length > 1) {
|
||||
if (lineData[0] != DiskLruCache.REMOVE) {
|
||||
filePath = this.path + lineData[1]
|
||||
let fileStat = fileio.statSync(filePath)
|
||||
if (fileStat.isFile() && fileStat.size > 0) {
|
||||
this.size = this.size + fileStat.size
|
||||
FileUtils.getInstance().writeData(this.journalPath, line + FileReader.LF)
|
||||
this.putCacheMap(lineData[1], fileStat.size)
|
||||
}
|
||||
} else {
|
||||
if (this.cacheMap.hasKey(lineData[1])) {
|
||||
let cacheEntry: DiskCacheEntry = this.cacheMap.get(lineData[1]) as DiskCacheEntry;
|
||||
this.size = this.size - cacheEntry.getLength()
|
||||
this.cacheMap.remove(lineData[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('DiskLruCache - dealWithJournal e ' + e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置journal文件数据
|
||||
*/
|
||||
private resetJournalFile() {
|
||||
FileUtils.getInstance().clearFile(this.journalPath)
|
||||
for (let key of this.cacheMap.keys()) {
|
||||
FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.SAVE + ' ' + key + FileReader.LF)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取journal文件的缓存数据
|
||||
*
|
||||
* @param path 日志缓存文件路径地址
|
||||
*/
|
||||
private readJournal(path: string) {
|
||||
let fileReader = new FileReader(path)
|
||||
let line: string = ''
|
||||
while (!fileReader.isEnd()) {
|
||||
line = fileReader.readLine()
|
||||
line = line.replace(FileReader.LF, '').replace(FileReader.CR, '')
|
||||
this.dealWithJournal(line)
|
||||
}
|
||||
fileReader.close()
|
||||
FileUtils.getInstance().deleteFile(this.journalPathTemp)
|
||||
this.trimToSize()
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存数据map集合
|
||||
*
|
||||
* @param key 键值
|
||||
* @param length 缓存文件大小
|
||||
*/
|
||||
private putCacheMap(key: string, length?: number) {
|
||||
if (length && length > 0) {
|
||||
this.cacheMap.put(key, new DiskCacheEntry(key, length))
|
||||
} else {
|
||||
this.cacheMap.put(key, new DiskCacheEntry(key))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据LRU算法删除多余缓存数据
|
||||
*/
|
||||
private trimToSize() {
|
||||
while (this.size > this.maxSize) {
|
||||
let tempKey: string = this.cacheMap.getFirstKey()
|
||||
let fileSize = FileUtils.getInstance().getFileSize(this.path + tempKey)
|
||||
if (fileSize > 0) {
|
||||
this.size = this.size - fileSize
|
||||
}
|
||||
FileUtils.getInstance().deleteFile(this.path + tempKey)
|
||||
this.cacheMap.remove(tempKey)
|
||||
FileUtils.getInstance().writeData(this.journalPath, DiskLruCache.REMOVE + ' ' + tempKey + FileReader.LF)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片文件过大 直接超过DiskLruCache上限
|
||||
*/
|
||||
private fileSizeMoreThenMaxSize(fileSize: number): boolean {
|
||||
if (fileSize > this.maxSize) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子线程里只写入缓存文件
|
||||
* @param context
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
static saveFileCacheOnlyFile(path: string, key: string, value: ArrayBuffer): boolean {
|
||||
// 写文件
|
||||
if (!!!key) {
|
||||
throw new Error('key is null, checking the parameter')
|
||||
}
|
||||
key = SparkMD5.hashBinary(key);
|
||||
FileUtils.getInstance()
|
||||
.writeData(path + DiskLruCache.journal, DiskLruCache.SAVE + ' ' + key + FileReader.LF);
|
||||
FileUtils.getInstance().writeNewFile(path + key, value);
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 子线程中,通过文件名,直接查找是否有文件缓存
|
||||
* @param context
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
static getFileCacheByFile(path: string, key: string): ArrayBuffer | undefined {
|
||||
// 从文件获取查看是否有缓存
|
||||
if (!!!key) {
|
||||
throw new Error('key is null,checking the parameter');
|
||||
}
|
||||
key = SparkMD5.hashBinary(key)
|
||||
let filepath = path + key;
|
||||
if (FileUtils.getInstance().exist(filepath)) {
|
||||
let ab: ArrayBuffer = FileUtils.getInstance().readFile(filepath)
|
||||
FileUtils.getInstance().writeData(path + DiskLruCache.journal, DiskLruCache.READ + ' ' + key + FileReader.LF)
|
||||
return ab
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加缓存键值对,但不写文件(用于子线程已经写文件的场景)
|
||||
setCacheMapAndSize(key: string, content: ArrayBuffer | string): void {
|
||||
if (!!!key) {
|
||||
throw new Error('key is null, checking the parameter')
|
||||
}
|
||||
let fileSize = 0;
|
||||
if (content instanceof ArrayBuffer) {
|
||||
if (content == null || content.byteLength == 0) {
|
||||
throw new Error('content is null. checking the parameter')
|
||||
}
|
||||
fileSize = content.byteLength
|
||||
} else {
|
||||
if (!!!content) {
|
||||
throw new Error('content is null, checking the parameter')
|
||||
}
|
||||
fileSize = content.length;
|
||||
}
|
||||
if (this.fileSizeMoreThenMaxSize(fileSize)) {
|
||||
throw new Error('content must be less then DiskLruCache Size, checking the parameter')
|
||||
return
|
||||
}
|
||||
key = SparkMD5.hashBinary(key);
|
||||
this.size = this.size + fileSize;
|
||||
this.putCacheMap(key, fileSize);
|
||||
this.trimToSize();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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 fs, { ReadOptions } from '@ohos.file.fs';
|
||||
import { RequestOption } from '../imageknife/RequestOption';
|
||||
|
||||
export class FileReader {
|
||||
// 换行符
|
||||
static readonly LF: string = '\n'
|
||||
// CR符
|
||||
static readonly CR: string = '\r'
|
||||
// 文件大小
|
||||
fileLength: number = 0
|
||||
// 读取的长度
|
||||
length: number = 0
|
||||
// 读写stream
|
||||
stream: fs.Stream
|
||||
// 缓存buf
|
||||
buf: ArrayBuffer = new ArrayBuffer(1)
|
||||
|
||||
/**
|
||||
* 读取文件行
|
||||
*
|
||||
* @param path 文件路径
|
||||
*/
|
||||
constructor(path: string) {
|
||||
if (!!!path) {
|
||||
throw new Error('FileReader constructor path is null, checking the parameter')
|
||||
return;
|
||||
}
|
||||
this.stream = fs.createStreamSync(path, 'r+');
|
||||
let stat = fs.statSync(path)
|
||||
this.fileLength = stat.size
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环读取文件数据
|
||||
*/
|
||||
readLine(): string {
|
||||
let line = ''
|
||||
while (this.stream && this.length < this.fileLength) {
|
||||
this.stream?.readSync(this.buf, { offset: this.length })
|
||||
this.length++
|
||||
let temp = String.fromCharCode(...new Uint8Array(this.buf));
|
||||
line = line + temp
|
||||
// check CRLF
|
||||
if (temp == FileReader.CR) {
|
||||
// 边界判断 首先拿到下一个字符判断是否是LF 如果是CRLF需要再向后挪一位
|
||||
if (this.length < this.fileLength) {
|
||||
let nextBuf = new ArrayBuffer(1)
|
||||
this.stream?.readSync(nextBuf, { offset: this.length })
|
||||
let nextTemp = String.fromCharCode(...new Uint8Array(nextBuf));
|
||||
// 如果是CRLF 需要给当前length+1 向后挪一位
|
||||
if (nextTemp == FileReader.LF) {
|
||||
this.length++
|
||||
}
|
||||
}
|
||||
// 如果不是CRLF 只有一个CR结尾length不用变
|
||||
return line;
|
||||
} else {
|
||||
// 判断LF情况
|
||||
if (temp == FileReader.LF) {
|
||||
return line
|
||||
}
|
||||
}
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否结束
|
||||
*/
|
||||
isEnd() {
|
||||
return this.fileLength <= 0 || this.length == this.fileLength
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭stream
|
||||
*/
|
||||
close() {
|
||||
this.stream?.closeSync()
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
import fs from '@ohos.file.fs';
|
||||
import { BusinessError } from '@ohos.base'
|
||||
export class FileUtils {
|
||||
static readonly SEPARATOR: string = '/'
|
||||
base64Str: string = ''
|
||||
private static sInstance: FileUtils;
|
||||
|
||||
|
@ -32,13 +33,21 @@ export class FileUtils {
|
|||
|
||||
/**
|
||||
* 新建文件
|
||||
*
|
||||
* @param path 文件绝对路径及文件名
|
||||
* @return number 文件句柄id
|
||||
*/
|
||||
createFile(path: string): number {
|
||||
return fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).fd
|
||||
let num = -1;
|
||||
try {
|
||||
num = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).fd
|
||||
} catch (e) {
|
||||
console.log("createFile err :" + e)
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param path 文件绝对路径及文件名
|
||||
|
@ -143,16 +152,20 @@ export class FileUtils {
|
|||
|
||||
/**
|
||||
* 判断path文件是否存在
|
||||
*
|
||||
* @param path 文件绝对路径
|
||||
*/
|
||||
exist(path: string): boolean {
|
||||
try {
|
||||
let stat = fs.statSync(path)
|
||||
return stat.isFile()
|
||||
} catch (e) {
|
||||
console.debug("FileUtils - fileutils exsit e" + e)
|
||||
console.log("path=>" + path)
|
||||
return false
|
||||
if (fs.accessSync(path)) {
|
||||
let stat = fs.statSync(path)
|
||||
return stat.isFile()
|
||||
}
|
||||
} catch (error) {
|
||||
let err: BusinessError = error as BusinessError;
|
||||
console.error("accessSync failed with error message: " + err.message + ", error code: " + err.code);
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,9 +331,84 @@ export class FileUtils {
|
|||
return tmpUint8Array
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步向path写入数据
|
||||
*
|
||||
* @param path 文件绝对路径
|
||||
* @param content 文件内容
|
||||
*/
|
||||
async writeDataAsync(path: string, content: ArrayBuffer | string): Promise<void> {
|
||||
let fd = (await fs.open(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)).fd
|
||||
let stat = await fs.stat(path)
|
||||
await fs.write(fd, content, { offset: stat.size })
|
||||
await fs.close(fd)
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步拷贝文件
|
||||
*
|
||||
* @param src 文件绝对路径及文件名
|
||||
* @param dest 拷贝到对应的路径
|
||||
*/
|
||||
async copyFileAsync(src: string, dest: string): Promise<void> {
|
||||
await fs.copyFile(src, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取路径path的文件
|
||||
*
|
||||
* @param path 文件绝对路径
|
||||
*/
|
||||
async readFileAsync(path: string): Promise<ArrayBuffer> {
|
||||
let stat = await fs.stat(path);
|
||||
let fd = (await fs.open(path, fs.OpenMode.READ_WRITE)).fd;
|
||||
let length = stat.size;
|
||||
let buf = new ArrayBuffer(length);
|
||||
await fs.read(fd, buf);
|
||||
return buf
|
||||
}
|
||||
|
||||
/**
|
||||
* 向path写入数据
|
||||
*
|
||||
* @param path 文件绝对路径
|
||||
* @param data 文件内容
|
||||
*/
|
||||
async writeNewFileAsync(path: string, data: ArrayBuffer | string): Promise<void> {
|
||||
let fd = (await fs.open(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)).fd
|
||||
await fs.truncate(fd)
|
||||
await fs.write(fd, data)
|
||||
await fs.fsync(fd)
|
||||
await fs.close(fd)
|
||||
}
|
||||
|
||||
|
||||
uint8ArrayToBuffer(array: Uint8Array): ArrayBuffer {
|
||||
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset)
|
||||
}
|
||||
|
||||
/**
|
||||
* 向path写入数据
|
||||
*
|
||||
* @param path 文件绝对路径
|
||||
* @param data 文件内容
|
||||
*/
|
||||
writeNewFile(path: string, data: ArrayBuffer | string) {
|
||||
this.createFile(path)
|
||||
this.writeFile(path, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取路径path的文件
|
||||
*
|
||||
* @param path 文件绝对路径
|
||||
*/
|
||||
readFile(path: string): ArrayBuffer {
|
||||
let fd = fs.openSync(path, fs.OpenMode.READ_WRITE).fd;
|
||||
let length = fs.statSync(path).size
|
||||
let buf = new ArrayBuffer(length);
|
||||
fs.readSync(fd, buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DiskLruCache } from "@ohos/disklrucache"
|
||||
import { DiskLruCache } from "../cache/DiskLruCache"
|
||||
import { EngineKeyFactories } from "../cache/key/EngineKeyFactories"
|
||||
import { EngineKeyInterface } from "../cache/key/EngineKeyInterface"
|
||||
import { RequestOption } from "../imageknife/RequestOption"
|
||||
import { RequestOption, Size } from "../imageknife/RequestOption"
|
||||
import { AsyncCallback } from "../imageknife/interface/AsyncCallback"
|
||||
import { PlaceHolderManager } from "../imageknife/holder/PlaceHolderManager"
|
||||
import { RetryHolderManager } from "../imageknife/holder/RetryHolderManager"
|
||||
|
@ -38,18 +38,25 @@ import { EasyLinkedHashMap } from './utils/base/EasyLinkedHashMap'
|
|||
import { MethodMutex } from './utils/base/MethodMutex'
|
||||
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'
|
||||
import { BusinessError } from '@kit.BasicServicesKit'
|
||||
import { taskpool } from '@kit.ArkTS'
|
||||
import { GIFFrame } from './utils/gif/GIFFrame'
|
||||
import emitter from '@ohos.events.emitter';
|
||||
|
||||
import { MemoryCacheProxy } from './requestmanage/MemoryCacheProxy'
|
||||
import { ObjectKey } from './ObjectKey'
|
||||
import { TaskParams } from './TaskParams'
|
||||
import { Constants } from './constants/Constants'
|
||||
|
||||
export class ImageKnife {
|
||||
static readonly SEPARATOR: string = '/'
|
||||
memoryCache: MemoryLruCache;
|
||||
diskMemoryCache: DiskLruCache;
|
||||
dataFetch: IDataFetch;
|
||||
resourceFetch: IResourceFetch<ArrayBuffer>;
|
||||
filesPath: string = ""; // data/data/包名/files目录
|
||||
|
||||
diskMemoryCache: DiskLruCache;
|
||||
memoryCacheProxy: MemoryCacheProxy<string, ImageKnifeData> = new MemoryCacheProxy(new MemoryLruCache(100, 100 * 1024 * 1024));
|
||||
headerMap: Map<string, Object> = new Map<string, Object>(); //定义全局map
|
||||
placeholderCache: string = "placeholderCache"
|
||||
runningMaps: EasyLinkedHashMap<string, RequestOption>;
|
||||
|
@ -78,10 +85,7 @@ export class ImageKnife {
|
|||
this.pausedMaps = new EasyLinkedHashMap();
|
||||
|
||||
// 构造方法传入size 为保存文件个数
|
||||
this.memoryCache = new MemoryLruCache(100,100*1024*1024);
|
||||
|
||||
// 创建disk缓存 传入的size 为多少比特 比如20KB 传入20*1024
|
||||
this.diskMemoryCache = DiskLruCache.create(ImageKnifeGlobal.getInstance().getHapContext());
|
||||
this.memoryCache = new MemoryLruCache(100, 100 * 1024 * 1024);
|
||||
|
||||
// 创建网络下载能力
|
||||
this.dataFetch = new DownloadClient();
|
||||
|
@ -92,13 +96,16 @@ export class ImageKnife {
|
|||
// 初始化本地 文件保存
|
||||
this.filesPath = (ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext).filesDir as string;
|
||||
|
||||
this.diskMemoryCache = DiskLruCache.create(ImageKnifeGlobal.getInstance()
|
||||
.getHapContext() as common.UIAbilityContext);
|
||||
|
||||
// 通用文件格式识别初始化
|
||||
this.fileTypeUtil = new FileTypeUtil();
|
||||
|
||||
this.engineKeyImpl = new EngineKeyFactories();
|
||||
|
||||
|
||||
}
|
||||
|
||||
//全局设置请求头调用方法
|
||||
addHeader(key: string, value: Object) {
|
||||
this.headerMap.set(key, value);
|
||||
|
@ -112,6 +119,10 @@ export class ImageKnife {
|
|||
return this.memoryCache;
|
||||
}
|
||||
|
||||
getMemoryCacheProxy(): MemoryCacheProxy<string, ImageKnifeData> {
|
||||
return this.memoryCacheProxy;
|
||||
}
|
||||
|
||||
public static with(context: Object): ImageKnifeGlobal {
|
||||
// 存入hapContext;
|
||||
let global: ImageKnifeGlobal = ImageKnifeGlobal.getInstance();
|
||||
|
@ -184,11 +195,11 @@ export class ImageKnife {
|
|||
|
||||
|
||||
// 设置缓存张数,缓存大小,单位字节
|
||||
public setLruCacheSize(size: number,memory:number) {
|
||||
public setLruCacheSize(size: number, memory: number) {
|
||||
if (this.memoryCache.map.size() <= 0) {
|
||||
this.memoryCache = new MemoryLruCache(size,memory);
|
||||
this.memoryCache = new MemoryLruCache(size, memory);
|
||||
} else {
|
||||
let newLruCache = new MemoryLruCache(size,memory);
|
||||
let newLruCache = new MemoryLruCache(size, memory);
|
||||
this.memoryCache.foreachLruCache((value: ImageKnifeData, key: string, map: Object) => {
|
||||
newLruCache.put(key, value);
|
||||
})
|
||||
|
@ -200,6 +211,7 @@ export class ImageKnife {
|
|||
this.dataFetch = fetch;
|
||||
}
|
||||
|
||||
|
||||
// 替代原来的DiskLruCache
|
||||
public replaceDiskLruCache(size: number) {
|
||||
this.diskMemoryCache.setMaxSize(size)
|
||||
|
@ -292,27 +304,29 @@ export class ImageKnife {
|
|||
request.addHeaderMap(this.headerMap)
|
||||
}
|
||||
|
||||
this.generateDataCacheKey(request)
|
||||
// 首先执行占位图 解析任务
|
||||
if (request.placeholderSrc) {
|
||||
PlaceHolderManager.execute(request)
|
||||
this.taskpoolLoadResource(request, Constants.PLACE_HOLDER);
|
||||
}
|
||||
// 其次执行重试占位图 解析任务
|
||||
if (request.retryholderSrc) {
|
||||
RetryHolderManager.execute(request)
|
||||
this.taskpoolLoadResource(request, Constants.RETRY_HOLDER);
|
||||
}
|
||||
|
||||
// 最后解析错误占位图
|
||||
if (request.errorholderSrc) {
|
||||
ErrorHolderManager.execute(request)
|
||||
this.taskpoolLoadResource(request, Constants.ERROR_HOLDER);
|
||||
}
|
||||
return this.parseSource(request);
|
||||
}
|
||||
|
||||
loadResources(request: RequestOption) {
|
||||
generateDataCacheKey(request: RequestOption) {
|
||||
let factories: EngineKeyInterface;
|
||||
let cacheKey: string;
|
||||
let transferKey: string;
|
||||
let dataKey: string;
|
||||
//设置全局缓存key
|
||||
if (this.engineKeyImpl) {
|
||||
factories = this.engineKeyImpl;
|
||||
} else {
|
||||
|
@ -344,19 +358,55 @@ export class ImageKnife {
|
|||
|
||||
let signature = request.signature;
|
||||
|
||||
cacheKey = factories.generateMemoryCacheKey(loadKey,size,transformed,dontAnimateFlag,signature);
|
||||
cacheKey = factories.generateMemoryCacheKey(loadKey, size, transformed, dontAnimateFlag, signature);
|
||||
|
||||
// 生成磁盘缓存变换后数据key 变换后数据保存在磁盘
|
||||
transferKey = factories.generateTransformedDiskCacheKey(loadKey,size,transformed,dontAnimateFlag,signature);
|
||||
transferKey = factories.generateTransformedDiskCacheKey(loadKey, size, transformed, dontAnimateFlag, signature);
|
||||
|
||||
// 生成磁盘缓存源数据key 原始数据保存在磁盘
|
||||
dataKey = factories.generateOriginalDiskCacheKey(loadKey,signature);
|
||||
|
||||
dataKey = factories.generateOriginalDiskCacheKey(loadKey, signature);
|
||||
if (request.placeholderSrc) {
|
||||
let placeholderLoadKey = '';
|
||||
if (typeof request.placeholderSrc == 'string') {
|
||||
placeholderLoadKey = request.placeholderSrc;
|
||||
} else {
|
||||
placeholderLoadKey = JSON.stringify(request.placeholderSrc);
|
||||
}
|
||||
request.placeholderCacheKey = this.generateCacheKey(placeholderLoadKey, size, dontAnimateFlag, signature)
|
||||
}
|
||||
if (request.retryholderSrc) {
|
||||
let retryholderLoadKey = '';
|
||||
if (typeof request.retryholderSrc == 'string') {
|
||||
retryholderLoadKey = request.retryholderSrc;
|
||||
} else {
|
||||
retryholderLoadKey = JSON.stringify(request.retryholderSrc);
|
||||
}
|
||||
request.retryholderCacheKey = this.generateCacheKey(retryholderLoadKey, size, dontAnimateFlag, signature)
|
||||
}
|
||||
if (request.errorholderSrc) {
|
||||
let errorholderLoadKey = '';
|
||||
if (typeof request.errorholderSrc == 'string') {
|
||||
errorholderLoadKey = request.errorholderSrc;
|
||||
} else {
|
||||
errorholderLoadKey = JSON.stringify(request.errorholderSrc);
|
||||
}
|
||||
request.errorholderCacheKey = this.generateCacheKey(errorholderLoadKey, size, dontAnimateFlag, signature)
|
||||
}
|
||||
request.generateCacheKey = cacheKey;
|
||||
request.generateResourceKey = transferKey;
|
||||
request.generateDataKey = dataKey;
|
||||
}
|
||||
|
||||
this.loadCacheManager(request);
|
||||
private generateCacheKey(loadkey: string, size: string, dontAnimateFlag: boolean, signature?: ObjectKey) {
|
||||
let factories: EngineKeyInterface;
|
||||
|
||||
//设置全局缓存key
|
||||
if (this.engineKeyImpl) {
|
||||
factories = this.engineKeyImpl;
|
||||
} else {
|
||||
factories = new EngineKeyFactories();
|
||||
}
|
||||
return factories.generateMemoryCacheKey(loadkey, size, '', dontAnimateFlag, signature);
|
||||
}
|
||||
|
||||
// 删除执行结束的running
|
||||
|
@ -365,7 +415,7 @@ export class ImageKnife {
|
|||
|
||||
} else {
|
||||
this.runningMaps.remove(request.uuid);
|
||||
console.log('dodo runningMaps length =' + this.runningMaps.size())
|
||||
LogUtil.log('dodo runningMaps length =' + this.runningMaps.size())
|
||||
let previousRequest = request;
|
||||
this.loadNextPending(previousRequest);
|
||||
}
|
||||
|
@ -375,12 +425,11 @@ export class ImageKnife {
|
|||
private keyEqualPendingToRun(nextPending: RequestOption) {
|
||||
|
||||
|
||||
|
||||
|
||||
this.pendingMaps.remove(nextPending.uuid)
|
||||
this.runningMaps.put(nextPending.uuid, nextPending);
|
||||
|
||||
RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||
// RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||
this.taskpoolLoadResource(nextPending, Constants.MAIN_HOLDER);
|
||||
|
||||
}
|
||||
|
||||
|
@ -410,7 +459,8 @@ export class ImageKnife {
|
|||
let nextPending = pendingTailNode.value;
|
||||
this.runningMaps.put(nextPending.uuid, nextPending)
|
||||
this.pendingMaps.remove(nextPending.uuid)
|
||||
RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||
//RequestManager.execute((nextPending as RequestOption), this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||
this.taskpoolLoadResource(nextPending, Constants.MAIN_HOLDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,7 +478,7 @@ export class ImageKnife {
|
|||
}
|
||||
|
||||
if (hasEqualRunning) {
|
||||
if(tailNode != null && tailNode.value != null) {
|
||||
if (tailNode != null && tailNode.value != null) {
|
||||
this.keyEqualPendingToRun(tailNode.value);
|
||||
}
|
||||
} else {
|
||||
|
@ -462,9 +512,7 @@ export class ImageKnife {
|
|||
} else {
|
||||
this.runningMaps.put(request.uuid, request)
|
||||
|
||||
|
||||
// 不存在相同key的 任务可以并行
|
||||
RequestManager.execute(request, this.memoryCache, this.diskMemoryCache, this.dataFetch, this.resourceFetch)
|
||||
this.taskpoolLoadResource(request, Constants.MAIN_HOLDER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -473,6 +521,121 @@ export class ImageKnife {
|
|||
}
|
||||
}
|
||||
|
||||
//组装任务参数
|
||||
private assembleTaskParams(request: RequestOption, usageType: string) {
|
||||
//图片变换方法无法直接传递到子线程,这里先把对象名和构造参数传递到子线程,然后在子线程中实例化变换方法
|
||||
let transformations: string [][] = [];
|
||||
if (usageType == Constants.MAIN_HOLDER) {
|
||||
for (let i = 0; i < request.transformations.length; i++) {
|
||||
transformations.push([request.transformations[i].getClassName(), request.transformations[i].getConstructorParams()])
|
||||
}
|
||||
}
|
||||
let displayProgress = request.progressFunc ? true : false;
|
||||
//將要传递到子线程的参数,放在一个json对象上,避免方法参数过多
|
||||
let taskParams: TaskParams = {
|
||||
headers: request.headers,
|
||||
moduleContext: request.moduleContext,
|
||||
transformations: transformations,
|
||||
usageType: usageType,
|
||||
displayProgress: displayProgress,
|
||||
uuid: request.uuid,
|
||||
dontAnimateFlag: request.dontAnimateFlag,
|
||||
generateCacheKey: request.generateCacheKey,
|
||||
generateResourceKey: request.generateResourceKey,
|
||||
generateDataKey: request.generateDataKey,
|
||||
thumbSizeMultiplier: request.thumbSizeMultiplier,
|
||||
thumbDelayTime: request.thumbDelayTime,
|
||||
size: request.size,
|
||||
onlyRetrieveFromCache: request.onlyRetrieveFromCache,
|
||||
gpuEnabled: request.gpuEnabled,
|
||||
signature: request.signature,
|
||||
isCacheable: request.isCacheable
|
||||
}
|
||||
return taskParams;
|
||||
}
|
||||
|
||||
//多线程请求加载资源
|
||||
private taskpoolLoadResource(request: RequestOption, usageType: string) {
|
||||
let mainCache = this.memoryCacheProxy.loadMemoryCache(request.generateCacheKey, request.isCacheable);
|
||||
let placeholderCache = this.memoryCacheProxy.loadMemoryCache(request.placeholderCacheKey, request.isCacheable);
|
||||
let retryholderCache = this.memoryCacheProxy.loadMemoryCache(request.retryholderCacheKey, request.isCacheable);
|
||||
let errorholderCacheKey = this.memoryCacheProxy.loadMemoryCache(request.errorholderCacheKey, request.isCacheable);
|
||||
|
||||
if (usageType == Constants.PLACE_HOLDER && placeholderCache && !mainCache && !retryholderCache && !errorholderCacheKey) {
|
||||
LogUtil.info("imageknife load placeholder from MemoryCache")
|
||||
request.placeholderOnComplete(placeholderCache);
|
||||
return;
|
||||
} else if (usageType == Constants.RETRY_HOLDER && retryholderCache && !mainCache && !errorholderCacheKey) {
|
||||
LogUtil.info("imageknife load retryholder from MemoryCache")
|
||||
request.retryholderOnComplete(retryholderCache);
|
||||
return;
|
||||
} else if (usageType == Constants.ERROR_HOLDER && errorholderCacheKey && !mainCache) {
|
||||
LogUtil.info("imageknife load errorholder from MemoryCache")
|
||||
request.errorholderOnComplete(errorholderCacheKey);
|
||||
return;
|
||||
} else if (usageType == Constants.MAIN_HOLDER && mainCache) {
|
||||
LogUtil.info("imageknife load mainsource from MemoryCache")
|
||||
mainCache.waitSaveDisk = false;
|
||||
request.loadComplete(mainCache);
|
||||
return;
|
||||
}
|
||||
|
||||
let taskParams: TaskParams = this.assembleTaskParams(request, usageType);
|
||||
let loadSrcJson = JSON.stringify({
|
||||
loadSrc: request.loadSrc,
|
||||
placeholderSrc: request.placeholderSrc,
|
||||
errorholderSrc: request.errorholderSrc,
|
||||
retryholderSrc: request.retryholderSrc,
|
||||
});
|
||||
//使用taskpool多线程执行资源下载
|
||||
let task = new taskpool.Task(taskExecute, taskParams, loadSrcJson)
|
||||
task.setTransferList([])
|
||||
|
||||
emitter.on(Constants.PROGRESS_EMITTER, (data) => {
|
||||
if (request.progressFunc && data?.data?.value) {
|
||||
let percent = data.data.value as number;
|
||||
request.progressFunc.asyncSuccess(percent);
|
||||
}
|
||||
});
|
||||
taskpool.execute(task).then((data) => {
|
||||
if (usageType == Constants.PLACE_HOLDER) {
|
||||
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
||||
request.placeholderOnComplete(imageKnifeData)
|
||||
} else {
|
||||
request.placeholderOnError("request placeholder error")
|
||||
}
|
||||
} else if (usageType == Constants.RETRY_HOLDER) {
|
||||
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
||||
request.retryholderOnComplete(imageKnifeData)
|
||||
} else {
|
||||
request.retryholderOnError("request retryholder error")
|
||||
}
|
||||
} else if (usageType == Constants.ERROR_HOLDER) {
|
||||
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
||||
request.errorholderOnComplete(imageKnifeData)
|
||||
} else {
|
||||
request.errorholderOnError("request errorholder error")
|
||||
}
|
||||
} else {
|
||||
if ((typeof (data as PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, data as PixelMap);
|
||||
request.loadComplete(imageKnifeData)
|
||||
} else if ((data as GIFFrame[]).length > 0) {
|
||||
let imageKnifeData = ImageKnifeData.createImageGIFFrame(ImageKnifeType.GIFFRAME, data as GIFFrame[]);
|
||||
request.loadComplete(imageKnifeData)
|
||||
} else {
|
||||
request.loadError("request resources error")
|
||||
}
|
||||
}
|
||||
}).catch((err: BusinessError | string) => {
|
||||
request.loadError(err)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private keyNotEmpty(request: RequestOption): boolean {
|
||||
if (
|
||||
request.generateCacheKey != null && request.generateCacheKey.length > 0 &&
|
||||
|
@ -522,17 +685,16 @@ export class ImageKnife {
|
|||
if ((typeof (request.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, request.loadSrc as PixelMap)
|
||||
request.loadComplete(imageKnifeData);
|
||||
} else
|
||||
if (typeof request.loadSrc == 'string') {
|
||||
// 进入三级缓存模型
|
||||
return this.loadResources(request);
|
||||
} else {
|
||||
} else if (typeof request.loadSrc == 'string') {
|
||||
// 进入三级缓存模型
|
||||
return this.loadCacheManager(request);
|
||||
} else {
|
||||
let res = request.loadSrc as Resource;
|
||||
if (typeof res.id != 'undefined' && typeof res.type != 'undefined') {
|
||||
// 进入三级缓存模型 本地资源不参与磁盘缓存
|
||||
let none = new NONE();
|
||||
request.diskCacheStrategy(none);
|
||||
this.loadResources(request);
|
||||
this.loadCacheManager(request);
|
||||
} else {
|
||||
LogUtil.error("输入参数有问题!")
|
||||
}
|
||||
|
@ -540,5 +702,87 @@ export class ImageKnife {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载资源子线程包含流程:网络请求资源->下载资源到本地->解码成ixelMap | GIFFrame[]->缓存到内存和磁盘
|
||||
* @param taskParams:任务参数,JSON字符串类型
|
||||
* @param headers:请求头
|
||||
* @param moduleContext:模块上下文
|
||||
* @returns
|
||||
*/
|
||||
@Concurrent
|
||||
async function taskExecute(taskParams: TaskParams, loadSrcJson: string): Promise<PixelMap | GIFFrame[]> {
|
||||
|
||||
let emitProgressPercent = (percentValue: number) => {
|
||||
let eventData: emitter.EventData = {
|
||||
data: {
|
||||
"value": percentValue,
|
||||
}
|
||||
};
|
||||
emitter.emit(Constants.PROGRESS_EMITTER, eventData)
|
||||
}
|
||||
|
||||
let transformations = taskParams.transformations;
|
||||
let usageType = taskParams.usageType;
|
||||
let displayProgress = taskParams.displayProgress;
|
||||
//子线程构造RequestOption对象
|
||||
let newRequestOption = new RequestOption();
|
||||
let loadSrcObj: object = JSON.parse(loadSrcJson);
|
||||
newRequestOption.uuid = taskParams.uuid;
|
||||
newRequestOption.loadSrc = loadSrcObj["loadSrc"] as string | PixelMap | Resource;
|
||||
newRequestOption.dontAnimateFlag = taskParams.dontAnimateFlag;
|
||||
newRequestOption.generateCacheKey = taskParams.generateCacheKey;
|
||||
newRequestOption.generateResourceKey = taskParams.generateResourceKey;
|
||||
newRequestOption.generateDataKey = taskParams.generateDataKey;
|
||||
newRequestOption.thumbSizeMultiplier = taskParams.thumbSizeMultiplier;
|
||||
newRequestOption.thumbDelayTime = taskParams.thumbDelayTime;
|
||||
newRequestOption.size = taskParams.size;
|
||||
|
||||
newRequestOption.placeholderSrc = loadSrcObj["placeholderSrc"] as PixelMap | Resource | undefined;
|
||||
newRequestOption.errorholderSrc = loadSrcObj["errorholderSrc"] as PixelMap | Resource | undefined;
|
||||
newRequestOption.retryholderSrc = loadSrcObj["retryholderSrc"] as PixelMap | Resource | undefined;
|
||||
newRequestOption.onlyRetrieveFromCache = taskParams.onlyRetrieveFromCache;
|
||||
newRequestOption.gpuEnabled = taskParams.gpuEnabled;
|
||||
newRequestOption.headers = taskParams.headers;
|
||||
newRequestOption.signature = taskParams.signature;
|
||||
ImageKnifeGlobal.getInstance().setHapContext(taskParams.moduleContext as common.UIAbilityContext);
|
||||
newRequestOption.moduleContext = taskParams.moduleContext;
|
||||
newRequestOption.isCacheable = taskParams.isCacheable;
|
||||
|
||||
if (displayProgress) {
|
||||
newRequestOption.addProgressListener({
|
||||
asyncSuccess: (percentValue: number) => {
|
||||
// 如果进度条百分比 未展示大小,展示其动画
|
||||
emitProgressPercent(percentValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
//如果是本地图片不作磁盘缓存
|
||||
if (typeof newRequestOption.loadSrc !== 'string') {
|
||||
let none = new NONE();
|
||||
newRequestOption.diskCacheStrategy(none);
|
||||
}
|
||||
|
||||
if (usageType == Constants.PLACE_HOLDER) {
|
||||
let manager = new PlaceHolderManager<PixelMap>(newRequestOption);
|
||||
return await new Promise<PixelMap>(manager.process);
|
||||
} else if (usageType == Constants.RETRY_HOLDER) {
|
||||
let manager = new RetryHolderManager<PixelMap>(newRequestOption);
|
||||
return await new Promise<PixelMap>(manager.process);
|
||||
} else if (usageType == Constants.ERROR_HOLDER) {
|
||||
let manager = new ErrorHolderManager<PixelMap>(newRequestOption);
|
||||
return await new Promise<PixelMap>(manager.process);
|
||||
} else {
|
||||
if (transformations) {
|
||||
for (let i = 0; i < transformations.length; i++) {
|
||||
let className = transformations[i][0] as string;
|
||||
let params = transformations[i][1] as string;
|
||||
newRequestOption.addTransformations(className, params);
|
||||
}
|
||||
}
|
||||
let newDataFetch = new DownloadClient();
|
||||
let newResourceFetch = new ParseResClient();
|
||||
let manager = new RequestManager(newRequestOption, newDataFetch, newResourceFetch);
|
||||
return await new Promise<PixelMap | GIFFrame[]>(manager.process);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ export struct ImageKnifeComponent {
|
|||
// 抗锯齿属性
|
||||
private imageSmoothingQuality: ImageSmoothingQuality = 'low';
|
||||
private imageSmoothingEnabled: boolean = true;
|
||||
// 是否是gif图片
|
||||
private isGif: boolean = false
|
||||
@State keyCanvas: KeyCanvas = {
|
||||
keyId: util.generateRandomUUID()
|
||||
}
|
||||
|
@ -197,6 +199,11 @@ export struct ImageKnifeComponent {
|
|||
request.load(this.imageKnifeOption.loadSrc)
|
||||
.addListener({ callback: (err:BusinessError|string, data:ImageKnifeData) => {
|
||||
LogUtil.log('ImageKnifeComponent request.load callback')
|
||||
if(data.isGIFFrame()) {
|
||||
this.isGif = true
|
||||
} else {
|
||||
this.isGif = false
|
||||
}
|
||||
this.runNextFunction(this.displayMainSource,data);
|
||||
return false;
|
||||
}
|
||||
|
@ -241,20 +248,20 @@ export struct ImageKnifeComponent {
|
|||
}
|
||||
if (this.imageKnifeOption.placeholderSrc) {
|
||||
request.placeholder(this.imageKnifeOption.placeholderSrc, {asyncSuccess:(data:ImageKnifeData) => {
|
||||
LogUtil.log('ImageKnifeComponent request.placeholder callback')
|
||||
LogUtil.log('ImageKnife ImageKnifeComponent request.placeholder callback')
|
||||
this.runNextFunction(this.displayPlaceholder,data)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (this.imageKnifeOption.thumbSizeMultiplier) {
|
||||
request.thumbnail(this.imageKnifeOption.thumbSizeMultiplier, {asyncSuccess:(data:ImageKnifeData) => {
|
||||
LogUtil.log('ImageKnifeComponent request.thumbnail callback')
|
||||
LogUtil.log('ImageKnife ImageKnifeComponent request.thumbnail callback')
|
||||
this.runNextFunction(this.displayThumbSizeMultiplier,data)
|
||||
}}, this.imageKnifeOption.thumbSizeDelay)
|
||||
}
|
||||
if (this.imageKnifeOption.errorholderSrc) {
|
||||
request.errorholder(this.imageKnifeOption.errorholderSrc, {asyncSuccess:(data:ImageKnifeData) => {
|
||||
LogUtil.log('ImageKnifeComponent request.errorholder callback')
|
||||
LogUtil.log('ImageKnife ImageKnifeComponent request.errorholder callback')
|
||||
this.runNextFunction(this.displayErrorholder,data)
|
||||
}})
|
||||
}
|
||||
|
@ -276,14 +283,14 @@ export struct ImageKnifeComponent {
|
|||
if (this.imageKnifeOption.displayProgress) {
|
||||
request.addProgressListener({asyncSuccess:(percentValue: number) => {
|
||||
// 如果进度条百分比 未展示大小,展示其动画
|
||||
LogUtil.log('ImageKnifeComponent request.addProgressListener callback')
|
||||
LogUtil.log('ImageKnife ImageKnifeComponent request.addProgressListener callback')
|
||||
this.runNextFunction(this.displayProgress,percentValue)
|
||||
}})
|
||||
}
|
||||
|
||||
if (this.imageKnifeOption.retryholderSrc) {
|
||||
request.retryholder(this.imageKnifeOption.retryholderSrc,{asyncSuccess: (data:ImageKnifeData) => {
|
||||
LogUtil.log('ImageKnifeComponent request.retryholder callback')
|
||||
LogUtil.log('ImageKnife ImageKnifeComponent request.retryholder callback')
|
||||
this.hasDisplayRetryholder = true
|
||||
this.runNextFunction(this.displayRetryholder,data)
|
||||
}})
|
||||
|
@ -323,7 +330,7 @@ export struct ImageKnifeComponent {
|
|||
this.configNecessary(request);
|
||||
this.configCacheStrategy(request);
|
||||
this.configDisplay(request);
|
||||
this.configHspContext(request)
|
||||
this.configHspContext(request);
|
||||
this.configRenderGpu(request);
|
||||
if(ImageKnifeGlobal.getInstance().getImageKnife()!=undefined) {
|
||||
ImageKnifeGlobal.getInstance().getImageKnife()?.call(request);
|
||||
|
@ -467,7 +474,18 @@ export struct ImageKnifeComponent {
|
|||
|
||||
drawPlaceholder(context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) {
|
||||
LogUtil.log('ImageKnifeComponent default drawPlaceholder start!')
|
||||
|
||||
// API12 getImageInfoSync同步
|
||||
// if(data.drawPixelMap?.imagePixelMap != undefined) {
|
||||
// let imageInfo = data.drawPixelMap?.imagePixelMap.getImageInfoSync()
|
||||
// LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
// let scaleType = (typeof imageKnifeOption.placeholderScaleType == 'number') ? imageKnifeOption.placeholderScaleType : ScaleType.FIT_CENTER
|
||||
// context.save();
|
||||
// context.clearRect(0, 0, compWidth, compHeight)
|
||||
// ScaleTypeHelper.drawImageWithScaleType(context, scaleType, data.drawPixelMap?.imagePixelMap, px2vp(imageInfo.size.width), px2vp(imageInfo.size.height), compWidth, compHeight, 0, 0)
|
||||
// context.restore();
|
||||
// LogUtil.log('ImageKnifeComponent default drawPlaceholder end!')
|
||||
// }
|
||||
// getImageInfo异步
|
||||
data.drawPixelMap?.imagePixelMap?.getImageInfo().then((imageInfo) => {
|
||||
LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
let scaleType = (typeof imageKnifeOption.placeholderScaleType == 'number') ? imageKnifeOption.placeholderScaleType : ScaleType.FIT_CENTER
|
||||
|
@ -522,7 +540,18 @@ export struct ImageKnifeComponent {
|
|||
|
||||
drawThumbSizeMultiplier(context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) {
|
||||
LogUtil.log('ImageKnifeComponent default drawThumbSizeMultiplier start!')
|
||||
|
||||
// API12 getImageInfoSync同步
|
||||
// if(data.drawPixelMap?.imagePixelMap != undefined) {
|
||||
// let imageInfo = data.drawPixelMap?.imagePixelMap.getImageInfoSync()
|
||||
// LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
// let scaleType = (typeof imageKnifeOption.thumbSizeMultiplierScaleType == 'number') ? imageKnifeOption.thumbSizeMultiplierScaleType : ScaleType.FIT_CENTER
|
||||
// context.save();
|
||||
// context.clearRect(0, 0, compWidth, compHeight)
|
||||
// ScaleTypeHelper.drawImageWithScaleType(context, scaleType, data.drawPixelMap?.imagePixelMap, px2vp(imageInfo.size.width), px2vp(imageInfo.size.height), compWidth, compHeight, 0, 0)
|
||||
// context.restore();
|
||||
// LogUtil.log('ImageKnifeComponent default drawThumbSizeMultiplier end!')
|
||||
// }
|
||||
// getImageInfo异步
|
||||
data.drawPixelMap?.imagePixelMap?.getImageInfo().then((imageInfo) => {
|
||||
LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
let scaleType = (typeof imageKnifeOption.thumbSizeMultiplierScaleType == 'number') ? imageKnifeOption.thumbSizeMultiplierScaleType : ScaleType.FIT_CENTER
|
||||
|
@ -537,6 +566,18 @@ export struct ImageKnifeComponent {
|
|||
drawMainSource(context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) {
|
||||
LogUtil.log('ImageKnifeComponent default drawMainSource start!')
|
||||
if (data.isPixelMap()) {
|
||||
// API12 getImageInfoSync同步
|
||||
// if(data.drawPixelMap?.imagePixelMap != undefined) {
|
||||
// let imageInfo = data.drawPixelMap?.imagePixelMap.getImageInfoSync()
|
||||
// let scaleType = (typeof imageKnifeOption.mainScaleType == 'number') ? imageKnifeOption.mainScaleType : ScaleType.FIT_CENTER
|
||||
// LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height + 'scaleType=' + scaleType)
|
||||
// context.save();
|
||||
// context.clearRect(0, 0, compWidth, compHeight)
|
||||
// ScaleTypeHelper.drawImageWithScaleType(context, scaleType, data.drawPixelMap?.imagePixelMap, px2vp(imageInfo.size.width), px2vp(imageInfo.size.height), compWidth, compHeight, 0, 0)
|
||||
// context.restore();
|
||||
// LogUtil.log('ImageKnifeComponent default drawMainSource end!')
|
||||
// }
|
||||
// getImageInfo异步
|
||||
data.drawPixelMap?.imagePixelMap?.getImageInfo().then((imageInfo) => {
|
||||
let scaleType = (typeof imageKnifeOption.mainScaleType == 'number') ? imageKnifeOption.mainScaleType : ScaleType.FIT_CENTER
|
||||
LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height + 'scaleType=' + scaleType)
|
||||
|
@ -561,7 +602,18 @@ export struct ImageKnifeComponent {
|
|||
|
||||
drawRetryholder(context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) {
|
||||
LogUtil.log('ImageKnifeComponent default drawRetryholder start!')
|
||||
|
||||
// API12 getImageInfoSync同步
|
||||
// if(data.drawPixelMap?.imagePixelMap != undefined) {
|
||||
// let imageInfo = data.drawPixelMap?.imagePixelMap.getImageInfoSync()
|
||||
// LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
// let scaleType = (typeof imageKnifeOption.retryholderScaleType == 'number') ? imageKnifeOption.retryholderScaleType : ScaleType.FIT_CENTER
|
||||
// context.save();
|
||||
// context.clearRect(0, 0, compWidth, compHeight)
|
||||
// ScaleTypeHelper.drawImageWithScaleType(context, scaleType, data.drawPixelMap?.imagePixelMap, px2vp(imageInfo.size.width), px2vp(imageInfo.size.height), compWidth, compHeight, 0, 0)
|
||||
// context.restore();
|
||||
// LogUtil.log('ImageKnifeComponent default drawRetryholder end!')
|
||||
// }
|
||||
// getImageInfo异步
|
||||
data.drawPixelMap?.imagePixelMap?.getImageInfo().then((imageInfo) => {
|
||||
LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
let scaleType = (typeof imageKnifeOption.retryholderScaleType == 'number') ? imageKnifeOption.retryholderScaleType : ScaleType.FIT_CENTER
|
||||
|
@ -575,7 +627,18 @@ export struct ImageKnifeComponent {
|
|||
|
||||
drawErrorholder(context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) {
|
||||
LogUtil.log('ImageKnifeComponent default drawErrorholder start!')
|
||||
|
||||
// API12 getImageInfoSync同步
|
||||
// if(data.drawPixelMap?.imagePixelMap != undefined) {
|
||||
// let imageInfo = data.drawPixelMap?.imagePixelMap.getImageInfoSync()
|
||||
// LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
// let scaleType = (typeof imageKnifeOption.errorholderSrcScaleType == 'number') ? imageKnifeOption.errorholderSrcScaleType : ScaleType.FIT_CENTER
|
||||
// context.save();
|
||||
// context.clearRect(0, 0, compWidth, compHeight)
|
||||
// ScaleTypeHelper.drawImageWithScaleType(context, scaleType, data.drawPixelMap?.imagePixelMap, px2vp(imageInfo.size.width), px2vp(imageInfo.size.height), compWidth, compHeight, 0, 0)
|
||||
// context.restore();
|
||||
// LogUtil.log('ImageKnifeComponent default drawErrorholder end!')
|
||||
// }
|
||||
// getImageInfo异步
|
||||
data.drawPixelMap?.imagePixelMap?.getImageInfo().then((imageInfo) => {
|
||||
LogUtil.log('ImageKnifeComponent imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height)
|
||||
let scaleType = (typeof imageKnifeOption.errorholderSrcScaleType == 'number') ? imageKnifeOption.errorholderSrcScaleType : ScaleType.FIT_CENTER
|
||||
|
@ -650,7 +713,9 @@ export struct ImageKnifeComponent {
|
|||
if (this.detachFromLayoutPixelMap != undefined) {
|
||||
this.detachFromLayoutPixelMap.detach();
|
||||
}
|
||||
this.resetGifData();
|
||||
if(this.isGif){
|
||||
this.resetGifData();
|
||||
}
|
||||
this.listener.off("layout",this.onLayoutComplete)
|
||||
}
|
||||
|
||||
|
@ -804,7 +869,7 @@ export struct ImageKnifeComponent {
|
|||
ScaleTypeHelper.drawImageWithScaleType(context, scaleType, pixelmap, px2vp(frameW), px2vp(frameH), compWidth, compHeight, px2vp(frame.dims.left), px2vp(frame.dims.top))
|
||||
// tips:worker如果不是在展示页面中创建,使用子线程回来的数据创建的图片,会导致canvas绘制不出来
|
||||
context.restore();
|
||||
LogUtil.log('ImageKnifeComponent default drawMainSource end!')
|
||||
LogUtil.log('ImageKnifeComponent canvasDrawPixelMap end!')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {ImageKnife} from './ImageKnife'
|
||||
import { ImageKnife } from './ImageKnife'
|
||||
import { DiskStrategy } from "../cache/diskstrategy/DiskStrategy"
|
||||
import { AsyncCallback } from "../imageknife/interface/AsyncCallback"
|
||||
import { AsyncSuccess } from "../imageknife/interface/AsyncSuccess"
|
||||
import { IAllCacheInfoCallback } from "../imageknife/interface/IAllCacheInfoCallback"
|
||||
import { AsyncCallback } from "../imageknife/interface/AsyncCallback"
|
||||
import { AsyncSuccess } from "../imageknife/interface/AsyncSuccess"
|
||||
import { AllCacheInfo, IAllCacheInfoCallback } from "../imageknife/interface/IAllCacheInfoCallback"
|
||||
import { AUTOMATIC } from "../cache/diskstrategy/enum/AUTOMATIC"
|
||||
import { BaseTransform } from "../imageknife/transform/BaseTransform"
|
||||
import { RotateImageTransformation } from "../imageknife/transform/RotateImageTransformation"
|
||||
import { ImageKnifeData } from "../imageknife/ImageKnifeData"
|
||||
import { ImageKnifeData, ImageKnifeType } from "../imageknife/ImageKnifeData"
|
||||
import { CenterCrop } from '../imageknife/transform/pixelmap/CenterCrop'
|
||||
import { CenterInside } from '../imageknife/transform/pixelmap/CenterInside'
|
||||
import { FitCenter } from '../imageknife/transform/pixelmap/FitCenter'
|
||||
|
@ -28,7 +28,10 @@ import { RoundedCornersTransformation, RoundCorner } from '../imageknife/transfo
|
|||
|
||||
import { CropCircleTransformation } from '../imageknife/transform/CropCircleTransformation'
|
||||
|
||||
import { CropCircleWithBorderTransformation, rgbColor } from '../imageknife/transform/CropCircleWithBorderTransformation'
|
||||
import {
|
||||
CropCircleWithBorderTransformation,
|
||||
rgbColor
|
||||
} from '../imageknife/transform/CropCircleWithBorderTransformation'
|
||||
import { CropSquareTransformation } from '../imageknife/transform/CropSquareTransformation'
|
||||
import { CropTransformation } from '../imageknife/transform/CropTransformation'
|
||||
import { CropType } from '../imageknife/transform/CropTransformation'
|
||||
|
@ -50,28 +53,37 @@ import { ImageKnifeGlobal } from './ImageKnifeGlobal'
|
|||
import { BusinessError } from '@ohos.base'
|
||||
import { ObjectKey } from './ObjectKey'
|
||||
import common from '@ohos.app.ability.common'
|
||||
import { GIFFrame } from './utils/gif/GIFFrame'
|
||||
import { MemoryCacheProxy } from './requestmanage/MemoryCacheProxy'
|
||||
import { DiskCacheProxy } from './requestmanage/DiskCacheProxy'
|
||||
import { DiskLruCache } from '../cache/disklrucache'
|
||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'
|
||||
import { FileUtils } from '../cache/FileUtils'
|
||||
|
||||
export interface Size {
|
||||
width: number,
|
||||
height: number
|
||||
}
|
||||
export interface DetachFromLayout{
|
||||
detach:()=>void
|
||||
|
||||
export interface DetachFromLayout {
|
||||
detach: () => void
|
||||
}
|
||||
|
||||
export class RequestOption {
|
||||
// 遍历添加图片http请求头
|
||||
headers: Map<string, Object> = new Map<string, Object>();
|
||||
|
||||
// RequestOption调用header对于的方法
|
||||
addHeader(key: string, value: Object) {
|
||||
this.headers.set(key, value);
|
||||
}
|
||||
|
||||
// 全局调用header对应的方法,包含RequestOption的形式
|
||||
addHeaderMap(map: Map<string, Object>) {
|
||||
this.headers = map;
|
||||
}
|
||||
|
||||
uuid:string ='' // 唯一标识
|
||||
uuid: string = '' // 唯一标识
|
||||
loadSrc: string | PixelMap | Resource = '';
|
||||
strategy: DiskStrategy = new AUTOMATIC();
|
||||
dontAnimateFlag = false;
|
||||
|
@ -79,28 +91,23 @@ export class RequestOption {
|
|||
placeholderFunc: AsyncSuccess<ImageKnifeData> | undefined = undefined;
|
||||
errorholderSrc: PixelMap | Resource | undefined = undefined;
|
||||
errorholderFunc: AsyncSuccess<ImageKnifeData> | undefined = undefined;
|
||||
errorholderData: ImageKnifeData | undefined = undefined;;
|
||||
errorholderData: ImageKnifeData | undefined = undefined;
|
||||
thumbSizeMultiplier: number = 0;
|
||||
|
||||
// 如果存在缩略图,则主图延时1s加载
|
||||
thumbDelayTime: number = 1000
|
||||
thumbHolderFunc: AsyncSuccess<ImageKnifeData> | undefined = undefined;
|
||||
requestListeners: Array<AsyncCallback<ImageKnifeData>> | undefined = undefined;
|
||||
|
||||
// 进度条
|
||||
progressFunc: AsyncSuccess<number> | undefined = undefined;
|
||||
|
||||
// 重试图层
|
||||
retryholderSrc: PixelMap | Resource | undefined = undefined;
|
||||
retryholderFunc: AsyncSuccess<ImageKnifeData> | undefined = undefined;
|
||||
retryholderData: ImageKnifeData | undefined = undefined;
|
||||
size:Size= { width: -1, height: -1 };
|
||||
|
||||
size: Size = { width: -1, height: -1 };
|
||||
// 网络下载数据回调
|
||||
allCacheInfoCallback: IAllCacheInfoCallback | undefined = undefined;
|
||||
onlyRetrieveFromCache: boolean = false;
|
||||
isCacheable: boolean = true;
|
||||
|
||||
// 开启GPU变换绘制
|
||||
gpuEnabled: boolean = false;
|
||||
// 变换相关
|
||||
|
@ -110,40 +117,35 @@ export class RequestOption {
|
|||
generateDataKey: string = "";
|
||||
filesPath: string = ""; // data/data/包名/files目录
|
||||
cachesPath: string = ""; // 网络下载默认存储在data/data/包名/cache/ImageKnifeNetworkFolder/目标md5.img下面
|
||||
|
||||
placeholderCacheKey: string = "";
|
||||
retryholderCacheKey: string = "";
|
||||
errorholderCacheKey: string = "";
|
||||
// 自定义缓存关键字
|
||||
signature?: ObjectKey;
|
||||
|
||||
// 下载原始文件地址
|
||||
downloadFilePath: string = "";
|
||||
|
||||
// 网络文件下载统一存放
|
||||
networkCacheFolder: string = "ImageKnifeNetworkFolder"
|
||||
|
||||
|
||||
// 主线图片 状态变化 是否加载完成
|
||||
// 主图未加载成功 显示占位图 主图加载成功不展示占位图
|
||||
loadMainReady = false;
|
||||
|
||||
// 失败占位图展示状态 当true 表示主图加载失败需要展示失败占位图
|
||||
loadErrorReady = false;
|
||||
|
||||
// 重试占位图展示状态 当true 表示主图加载失败需要展示失败占位图
|
||||
loadRetryReady = false;
|
||||
|
||||
// 缩略图展示
|
||||
loadThumbnailReady = false;
|
||||
|
||||
detachFromLayout:DetachFromLayout = {
|
||||
detach: ()=>{
|
||||
let imageKnife:ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if(imageKnife != undefined) {
|
||||
detachFromLayout: DetachFromLayout = {
|
||||
detach: () => {
|
||||
let imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if (imageKnife != undefined) {
|
||||
imageKnife.remove(this.uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
// module资源的需要当前的module context
|
||||
moduleContext?:common.UIAbilityContext = undefined;
|
||||
moduleContext?: common.UIAbilityContext = undefined;
|
||||
|
||||
constructor() {
|
||||
// 初始化全局监听
|
||||
this.requestListeners = new Array();
|
||||
|
@ -151,32 +153,34 @@ export class RequestOption {
|
|||
this.uuid = this.generateUUID();
|
||||
|
||||
|
||||
let ctx = ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext
|
||||
if(ctx != undefined){
|
||||
let ctx = ImageKnifeGlobal.getInstance().getHapContext() as common.UIAbilityContext
|
||||
if (ctx != undefined) {
|
||||
this.moduleContext = ctx;
|
||||
}
|
||||
}
|
||||
|
||||
generateUUID(): string {
|
||||
let d = new Date().getTime();
|
||||
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( new RegExp("[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);
|
||||
});
|
||||
return uuid;
|
||||
}
|
||||
setModuleContext(moduleCtx:common.UIAbilityContext){
|
||||
|
||||
setModuleContext(moduleCtx: common.UIAbilityContext) {
|
||||
this.moduleContext = moduleCtx;
|
||||
}
|
||||
|
||||
getModuleContext():common.UIAbilityContext | undefined{
|
||||
getModuleContext(): common.UIAbilityContext | undefined {
|
||||
return this.moduleContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* set image Component size
|
||||
*/
|
||||
setImageViewSize(imageSize:Size) {
|
||||
setImageViewSize(imageSize: Size) {
|
||||
this.size.width = imageSize.width;
|
||||
this.size.height = imageSize.height;
|
||||
return this;
|
||||
|
@ -247,7 +251,7 @@ export class RequestOption {
|
|||
}
|
||||
|
||||
addListener(func: AsyncCallback<ImageKnifeData>) {
|
||||
if(this.requestListeners != undefined) {
|
||||
if (this.requestListeners != undefined) {
|
||||
this.requestListeners?.push(func);
|
||||
}
|
||||
return this;
|
||||
|
@ -267,8 +271,8 @@ export class RequestOption {
|
|||
this.onlyRetrieveFromCache = flag;
|
||||
}
|
||||
|
||||
rotateImage(degreesToRotate: number|undefined) {
|
||||
if(degreesToRotate == undefined){
|
||||
rotateImage(degreesToRotate: number | undefined) {
|
||||
if (degreesToRotate == undefined) {
|
||||
return
|
||||
}
|
||||
let rotateImage = new RotateImageTransformation(degreesToRotate);
|
||||
|
@ -291,8 +295,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
roundedCorners(obj: RoundCorner|undefined) {
|
||||
if(obj == undefined){
|
||||
roundedCorners(obj: RoundCorner | undefined) {
|
||||
if (obj == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new RoundedCornersTransformation({
|
||||
|
@ -311,8 +315,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
cropCircleWithBorder(border: number|undefined, obj: rgbColor|undefined) {
|
||||
if(border == undefined || obj == undefined){
|
||||
cropCircleWithBorder(border: number | undefined, obj: rgbColor | undefined) {
|
||||
if (border == undefined || obj == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new CropCircleWithBorderTransformation(border, obj)
|
||||
|
@ -326,8 +330,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
crop(width: number|undefined, height: number|undefined, cropType: CropType|undefined) {
|
||||
if(width == undefined || height == undefined || cropType == undefined){
|
||||
crop(width: number | undefined, height: number | undefined, cropType: CropType | undefined) {
|
||||
if (width == undefined || height == undefined || cropType == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new CropTransformation(width, height, cropType)
|
||||
|
@ -341,8 +345,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
brightnessFilter(brightness: number|undefined) {
|
||||
if(brightness == undefined){
|
||||
brightnessFilter(brightness: number | undefined) {
|
||||
if (brightness == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new BrightnessFilterTransformation(brightness)
|
||||
|
@ -350,8 +354,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
contrastFilter(contrast: number|undefined) {
|
||||
if(contrast == undefined){
|
||||
contrastFilter(contrast: number | undefined) {
|
||||
if (contrast == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new ContrastFilterTransformation(contrast)
|
||||
|
@ -377,22 +381,22 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
blur(radius: number|undefined , sampling?: number) {
|
||||
if(radius == undefined){
|
||||
blur(radius: number | undefined, sampling?: number) {
|
||||
if (radius == undefined) {
|
||||
return
|
||||
}
|
||||
if(sampling == undefined) {
|
||||
if (sampling == undefined) {
|
||||
let transformation = new BlurTransformation(radius)
|
||||
this.transformations.push(transformation);
|
||||
} else {
|
||||
let transformation = new BlurTransformation(radius,sampling)
|
||||
let transformation = new BlurTransformation(radius, sampling)
|
||||
this.transformations.push(transformation);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
pixelationFilter(pixel: number|undefined) {
|
||||
if(pixel == undefined){
|
||||
pixelationFilter(pixel: number | undefined) {
|
||||
if (pixel == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new PixelationFilterTransformation(pixel)
|
||||
|
@ -400,8 +404,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
swirlFilter(degree: number|undefined) {
|
||||
if(degree == undefined){
|
||||
swirlFilter(degree: number | undefined) {
|
||||
if (degree == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new SwirlFilterTransformation(degree)
|
||||
|
@ -409,8 +413,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
mask(maskResource: Resource|undefined) {
|
||||
if(maskResource == undefined){
|
||||
mask(maskResource: Resource | undefined) {
|
||||
if (maskResource == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new MaskTransformation(maskResource)
|
||||
|
@ -418,8 +422,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
kuwaharaFilter(radius: number|undefined) {
|
||||
if(radius == undefined){
|
||||
kuwaharaFilter(radius: number | undefined) {
|
||||
if (radius == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new KuwaharaFilterTransform(radius);
|
||||
|
@ -427,8 +431,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
toonFilter(threshold: number|undefined, quantizationLevels: number|undefined) {
|
||||
if(threshold == undefined || quantizationLevels == undefined){
|
||||
toonFilter(threshold: number | undefined, quantizationLevels: number | undefined) {
|
||||
if (threshold == undefined || quantizationLevels == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new ToonFilterTransform(threshold, quantizationLevels);
|
||||
|
@ -436,8 +440,8 @@ export class RequestOption {
|
|||
return this;
|
||||
}
|
||||
|
||||
vignetteFilter(centerPoint: Array<number>|undefined, vignetteColor: Array<number>|undefined, vignetteSpace: Array<number>|undefined) {
|
||||
if(centerPoint == undefined || vignetteColor == undefined || vignetteSpace == undefined){
|
||||
vignetteFilter(centerPoint: Array<number> | undefined, vignetteColor: Array<number> | undefined, vignetteSpace: Array<number> | undefined) {
|
||||
if (centerPoint == undefined || vignetteColor == undefined || vignetteSpace == undefined) {
|
||||
return
|
||||
}
|
||||
let transformation = new VignetteFilterTransform(centerPoint, vignetteColor, vignetteSpace);
|
||||
|
@ -454,6 +458,7 @@ export class RequestOption {
|
|||
this.transformations = inputs;
|
||||
return this;
|
||||
}
|
||||
|
||||
// 开启GPU变换绘制
|
||||
enableGPU() {
|
||||
this.gpuEnabled = true;
|
||||
|
@ -461,72 +466,78 @@ export class RequestOption {
|
|||
}
|
||||
|
||||
// 占位图解析成功
|
||||
placeholderOnComplete = (imageKnifeData: ImageKnifeData)=> {
|
||||
placeholderOnComplete = (imageKnifeData:ImageKnifeData) => {
|
||||
LogUtil.log("placeholderOnComplete has called!");
|
||||
LogUtil.log("Main Image is Ready:" + this.loadMainReady);
|
||||
this.setMemoryCache(imageKnifeData,this.placeholderCacheKey);
|
||||
if (!this.loadMainReady && !(this.loadErrorReady || this.loadRetryReady) && !this.loadThumbnailReady) {
|
||||
// 主图未加载成功,并且未加载失败 显示占位图 主图加载成功或者加载失败后=>不展示占位图
|
||||
if(this.placeholderSrc != undefined) {
|
||||
if (this.placeholderSrc != undefined) {
|
||||
this.placeholderFunc?.asyncSuccess(imageKnifeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 占位图解析失败
|
||||
placeholderOnError = (error:BusinessError|string)=>{
|
||||
placeholderOnError = (error: BusinessError | string) => {
|
||||
LogUtil.log("占位图解析失败 error =" + error)
|
||||
}
|
||||
|
||||
|
||||
// 缩略图解析成功
|
||||
thumbholderOnComplete = (imageKnifeData: ImageKnifeData)=> {
|
||||
thumbholderOnComplete = (value: PixelMap | GIFFrame[]) => {
|
||||
let imageKnifeData = new ImageKnifeData();
|
||||
if ((typeof (value as PixelMap).isEditable) == 'boolean') {
|
||||
imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value as PixelMap);
|
||||
} else {
|
||||
imageKnifeData = ImageKnifeData.createImageGIFFrame(ImageKnifeType.GIFFRAME, value as GIFFrame[]);
|
||||
}
|
||||
if (!this.loadMainReady && !(this.loadErrorReady || this.loadRetryReady)) {
|
||||
// 主图未加载成功,并且未加载失败 显示占位图 主图加载成功或者加载失败后=>不展示占位图
|
||||
if(this.thumbHolderFunc != undefined) {
|
||||
if (this.thumbHolderFunc != undefined) {
|
||||
this.thumbHolderFunc?.asyncSuccess(imageKnifeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 缩略图解析失败
|
||||
thumbholderOnError=(error? :BusinessError|string)=>{
|
||||
thumbholderOnError = (error?: BusinessError | string) => {
|
||||
LogUtil.log("缩略图解析失败 error =" + error)
|
||||
}
|
||||
|
||||
// 加载失败 占位图解析成功
|
||||
errorholderOnComplete = (imageKnifeData: ImageKnifeData)=> {
|
||||
errorholderOnComplete = (imageKnifeData:ImageKnifeData) => {
|
||||
this.setMemoryCache(imageKnifeData,this.errorholderCacheKey);
|
||||
// 如果有错误占位图 先解析并保存在RequestOption中 等到加载失败时候进行调用
|
||||
this.errorholderData = imageKnifeData;
|
||||
if (this.loadErrorReady) {
|
||||
if(this.errorholderFunc != undefined) {
|
||||
if (this.errorholderFunc != undefined) {
|
||||
this.errorholderFunc.asyncSuccess(imageKnifeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载失败 占位图解析失败
|
||||
errorholderOnError = (error:BusinessError|string)=> {
|
||||
errorholderOnError = (error: BusinessError | string) => {
|
||||
LogUtil.log("失败占位图解析失败 error =" + error)
|
||||
}
|
||||
|
||||
retryholderOnComplete = (imageKnifeData: ImageKnifeData)=>{
|
||||
retryholderOnComplete = (imageKnifeData:ImageKnifeData) => {
|
||||
this.setMemoryCache(imageKnifeData,this.retryholderCacheKey);
|
||||
this.retryholderData = imageKnifeData;
|
||||
if (this.loadRetryReady) {
|
||||
if(this.retryholderFunc != undefined) {
|
||||
if (this.retryholderFunc != undefined) {
|
||||
this.retryholderFunc?.asyncSuccess(imageKnifeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retryholderOnError = (error:BusinessError|string)=>{
|
||||
retryholderOnError = (error: BusinessError | string) => {
|
||||
LogUtil.log("重试占位图解析失败 error =" + error)
|
||||
}
|
||||
loadComplete = (imageKnifeData: ImageKnifeData) => {
|
||||
this.setMemoryCache(imageKnifeData,this.generateCacheKey);
|
||||
if (typeof this.loadSrc == 'string') {
|
||||
this.setDiskCache();
|
||||
}
|
||||
|
||||
loadComplete = (imageKnifeData: ImageKnifeData)=>{
|
||||
this.loadMainReady = true;
|
||||
|
||||
// 三级缓存数据加载成功
|
||||
if(this.requestListeners != undefined) {
|
||||
for (let i = 0;i < this.requestListeners.length; i++) {
|
||||
if (this.requestListeners != undefined) {
|
||||
for (let i = 0; i < this.requestListeners.length; i++) {
|
||||
let requestListener = this.requestListeners[i];
|
||||
let boolInterception = requestListener.callback("", imageKnifeData);
|
||||
if (boolInterception) {
|
||||
|
@ -534,32 +545,79 @@ export class RequestOption {
|
|||
}
|
||||
}
|
||||
}
|
||||
//输出缓存相关内容和信息
|
||||
if (this.allCacheInfoCallback) {
|
||||
// 内存缓存
|
||||
let allCacheInfo: AllCacheInfo = {
|
||||
memoryCacheInfo: { key: '', data: new ImageKnifeData() },
|
||||
resourceCacheInfo: { key: '', path: '' },
|
||||
dataCacheInfo: { key: '', path: '' }
|
||||
};
|
||||
allCacheInfo.memoryCacheInfo = {
|
||||
key: this.generateCacheKey,
|
||||
data: imageKnifeData
|
||||
}
|
||||
let mDiskCacheProxy = new DiskCacheProxy(DiskLruCache.create(ImageKnifeGlobal.getInstance()
|
||||
.getHapContext() as common.UIAbilityContext))
|
||||
// 变换后缓存
|
||||
allCacheInfo.resourceCacheInfo = {
|
||||
key: SparkMD5.hashBinary(this.generateResourceKey) as string,
|
||||
path: (mDiskCacheProxy.getCachePath() + SparkMD5.hashBinary(this.generateResourceKey)) as string
|
||||
};
|
||||
|
||||
if(imageKnifeData.waitSaveDisk){
|
||||
// 原图缓存
|
||||
allCacheInfo.dataCacheInfo = {
|
||||
key: SparkMD5.hashBinary(this.generateDataKey) as string,
|
||||
path: (mDiskCacheProxy.getCachePath() + SparkMD5.hashBinary(this.generateDataKey)) as string
|
||||
}
|
||||
this.allCacheInfoCallback.callback(allCacheInfo);
|
||||
}
|
||||
|
||||
if (imageKnifeData.waitSaveDisk) {
|
||||
// 等落盘结束后主动调用#removeCurrentAndSearchNext方法
|
||||
}else{
|
||||
} else {
|
||||
// 非落盘情况,直接进行寻找下一个加载
|
||||
let imageKnife:ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if(imageKnife != undefined) {
|
||||
let imageKnife: ImageKnife | undefined = ImageKnifeGlobal.getInstance().getImageKnife();
|
||||
if (imageKnife != undefined) {
|
||||
imageKnife.removeRunning(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
//设置内存缓存
|
||||
setMemoryCache = (imageKnifeData: ImageKnifeData,cacheKey:string) => {
|
||||
|
||||
let memoryCacheProxy = ImageKnifeGlobal.getInstance()
|
||||
.getImageKnife()?.getMemoryCacheProxy() as MemoryCacheProxy<string, ImageKnifeData>;
|
||||
memoryCacheProxy.putValue(cacheKey, imageKnifeData);
|
||||
}
|
||||
//设置磁盘缓存
|
||||
setDiskCache = () => {
|
||||
try {
|
||||
let diskMemoryCache = ImageKnifeGlobal.getInstance().getImageKnife()?.getDiskMemoryCache();
|
||||
let dataArraybuffer: ArrayBuffer = DiskLruCache.getFileCacheByFile((ImageKnifeGlobal.getInstance()
|
||||
.getHapContext() as common.UIAbilityContext).filesDir as string, this.generateDataKey) as ArrayBuffer;
|
||||
//缓存原图片
|
||||
if (dataArraybuffer && !diskMemoryCache?.get(this.generateDataKey)) {
|
||||
diskMemoryCache?.setCacheMapAndSize(this.generateDataKey, dataArraybuffer);
|
||||
}
|
||||
//缓存变换后图片
|
||||
let resourceArraybuffer: ArrayBuffer = DiskLruCache.getFileCacheByFile((ImageKnifeGlobal.getInstance()
|
||||
.getHapContext() as common.UIAbilityContext).filesDir as string, this.generateResourceKey) as ArrayBuffer;
|
||||
if (resourceArraybuffer && !diskMemoryCache?.get(this.generateResourceKey)) {
|
||||
diskMemoryCache?.setCacheMapAndSize(this.generateResourceKey, resourceArraybuffer);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
LogUtil.error("imageknife DiskMemoryCache setDiskCache error :" + e.message);
|
||||
}
|
||||
}
|
||||
// 图片文件落盘之后会自动去寻找下一个数据加载
|
||||
removeCurrentAndSearchNext =()=>{
|
||||
if(ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
||||
removeCurrentAndSearchNext = () => {
|
||||
if (ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
||||
(ImageKnifeGlobal.getInstance().getImageKnife())?.removeRunning(this);
|
||||
}
|
||||
}
|
||||
|
||||
loadError = (err:BusinessError|string)=>{
|
||||
loadError = (err: BusinessError | string) => {
|
||||
LogUtil.log("loadError:" + err);
|
||||
// 失败占位图展示规则
|
||||
if (this.retryholderFunc) {
|
||||
|
@ -572,16 +630,105 @@ export class RequestOption {
|
|||
// 失败图层标记,如果已经有数据直接展示失败图层
|
||||
this.loadErrorReady = true;
|
||||
if (this.errorholderData != null) {
|
||||
if(this.errorholderFunc != undefined) {
|
||||
if (this.errorholderFunc != undefined) {
|
||||
this.errorholderFunc.asyncSuccess(this.errorholderData)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 加载失败之后
|
||||
if(ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
||||
if (ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
||||
(ImageKnifeGlobal.getInstance().getImageKnife())?.removeRunning(this);
|
||||
}
|
||||
}
|
||||
addTransformations = (transformationName: string, params: string) => {
|
||||
switch (transformationName) {
|
||||
case "BlurTransformation":
|
||||
let paramList: number [] = JSON.parse(params);
|
||||
this.transformations.push(new BlurTransformation(paramList[0], paramList[1]));
|
||||
break;
|
||||
case "BrightnessFilterTransformation":
|
||||
let paramList1: number [] = JSON.parse(params);
|
||||
this.transformations.push(new BrightnessFilterTransformation(paramList1[0]));
|
||||
break;
|
||||
case "RotateImageTransformation":
|
||||
let paramList2: number [] = JSON.parse(params);
|
||||
this.transformations.push(new RotateImageTransformation(paramList2[0]));
|
||||
break;
|
||||
case "GrayscaleTransformation":
|
||||
this.transformations.push(new GrayscaleTransformation());
|
||||
break;
|
||||
case "BlurTransformation":
|
||||
let paramList3: number [] = JSON.parse(params);
|
||||
this.transformations.push(new BlurTransformation(paramList3[0]));
|
||||
break;
|
||||
case "ContrastFilterTransformation":
|
||||
let paramList4: number [] = JSON.parse(params);
|
||||
this.transformations.push(new ContrastFilterTransformation(paramList4[0]));
|
||||
break;
|
||||
case "CropCircleTransformation":
|
||||
this.transformations.push(new CropCircleTransformation());
|
||||
break;
|
||||
case "CropCircleWithBorderTransformation":
|
||||
let paramList5: (number | rgbColor) [] = JSON.parse(params);
|
||||
this.transformations.push(new CropCircleWithBorderTransformation(paramList5[0] as number, paramList5[1] as rgbColor));
|
||||
break;
|
||||
case "CropSquareTransformation":
|
||||
this.transformations.push(new CropSquareTransformation());
|
||||
break;
|
||||
case "InvertFilterTransformation":
|
||||
this.transformations.push(new InvertFilterTransformation());
|
||||
break;
|
||||
case "KuwaharaFilterTransform":
|
||||
let paramList7: number [] = JSON.parse(params);
|
||||
this.transformations.push(new KuwaharaFilterTransform(paramList7[0] as number));
|
||||
break;
|
||||
case "MaskTransformation":
|
||||
let paramList8: Resource [] = JSON.parse(params);
|
||||
this.transformations.push(new MaskTransformation(paramList8[0] as Resource));
|
||||
break;
|
||||
case "PixelationFilterTransformation":
|
||||
let paramList9: number [] = JSON.parse(params);
|
||||
this.transformations.push(new PixelationFilterTransformation(paramList9[0] as number));
|
||||
break;
|
||||
case "RoundedCornersTransformation":
|
||||
let paramList10: RoundCorner [] = JSON.parse(params);
|
||||
this.transformations.push(new RoundedCornersTransformation(paramList10[0] as RoundCorner));
|
||||
break;
|
||||
case "SepiaFilterTransformation":
|
||||
this.transformations.push(new SepiaFilterTransformation());
|
||||
break;
|
||||
case "SketchFilterTransformation":
|
||||
this.transformations.push(new SketchFilterTransformation());
|
||||
break;
|
||||
case "SwirlFilterTransformation":
|
||||
let paramList11: (number | Array<number>) [] = JSON.parse(params);
|
||||
this.transformations.push(new SwirlFilterTransformation(paramList11[0] as number, paramList11[1] as number, paramList11[2] as Array<number>));
|
||||
break;
|
||||
case "ToonFilterTransform":
|
||||
let paramList14: number [] = JSON.parse(params);
|
||||
this.transformations.push(new ToonFilterTransform(paramList14[0], paramList14[1]));
|
||||
break;
|
||||
case "VignetteFilterTransform":
|
||||
let paramList12: Array<number> [] = JSON.parse(params);
|
||||
this.transformations.push(new VignetteFilterTransform(paramList12[0], paramList12[1], paramList12[2]));
|
||||
break;
|
||||
case "CenterCrop":
|
||||
this.transformations.push(new CenterCrop());
|
||||
break;
|
||||
case "CenterInside":
|
||||
this.transformations.push(new CenterInside());
|
||||
break;
|
||||
case "FitCenter":
|
||||
this.transformations.push(new FitCenter());
|
||||
break;
|
||||
case "CropTransformation":
|
||||
let paramList13: (number | CropType) [] = JSON.parse(params);
|
||||
this.transformations.push(new CropTransformation(paramList13[0] as number, paramList13[1] as number, paramList13[2] as CropType));
|
||||
break;
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 { ObjectKey } from './ObjectKey';
|
||||
import { Size } from '../imageknife/RequestOption'
|
||||
import common from '@ohos.app.ability.common'
|
||||
|
||||
export class TaskParams {
|
||||
headers: Map<string, Object> = new Map<string, Object>();
|
||||
moduleContext?: common.UIAbilityContext = undefined;
|
||||
transformations: string [][] = []
|
||||
usageType: string = ''
|
||||
displayProgress: boolean = false
|
||||
uuid: string = '' // 唯一标识
|
||||
dontAnimateFlag: boolean = false;
|
||||
thumbSizeMultiplier: number = 0;
|
||||
thumbDelayTime: number = 1000;
|
||||
size: Size = { width: -1, height: -1 };
|
||||
onlyRetrieveFromCache: boolean = false;
|
||||
isCacheable: boolean = true;
|
||||
gpuEnabled: boolean = false;
|
||||
generateCacheKey: string = "";
|
||||
generateResourceKey: string = "";
|
||||
generateDataKey: string = "";
|
||||
signature?: ObjectKey;
|
||||
}
|
|
@ -14,5 +14,10 @@
|
|||
*/
|
||||
|
||||
export class Constants {
|
||||
public static PROJECT_TAG: string= "ImageKnife_js"
|
||||
public static PROJECT_TAG: string = "ImageKnife_js"
|
||||
public static PROGRESS_EMITTER: string = "progressEmitter"
|
||||
public static PLACE_HOLDER: string = "placeholder"
|
||||
public static RETRY_HOLDER: string = "retryholder"
|
||||
public static ERROR_HOLDER: string = "errorholder"
|
||||
public static MAIN_HOLDER: string = "main"
|
||||
}
|
|
@ -31,21 +31,15 @@ export class ErrorHolderManager<T> {
|
|||
this.options = option;
|
||||
}
|
||||
|
||||
static execute(option: RequestOption) {
|
||||
let manager:ErrorHolderManager<ImageKnifeData> = new ErrorHolderManager<ImageKnifeData>(option);
|
||||
return new Promise(manager.process)
|
||||
.then(option.errorholderOnComplete).catch(option.errorholderOnError);
|
||||
}
|
||||
|
||||
process = (onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
process = (onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
this.displayErrorholder(onComplete, onError);
|
||||
}
|
||||
|
||||
private displayErrorholder(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
private displayErrorholder(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("displayErrorholder")
|
||||
if ((typeof (this.options.errorholderSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, this.options.errorholderSrc as PixelMap)
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap);
|
||||
} else if (typeof this.options.errorholderSrc == 'string') {
|
||||
|
||||
} else {
|
||||
|
@ -89,16 +83,16 @@ export class ErrorHolderManager<T> {
|
|||
}
|
||||
}
|
||||
|
||||
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
private svgProcess(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
let svgParseImpl:SVGParseImpl = new SVGParseImpl()
|
||||
svgParseImpl.parseSvg(this.options,arraybuffer, onComplete,onError);
|
||||
}
|
||||
|
||||
private mediaImageProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
private mediaImageProcess(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
let parseImageUtil = new ParseImageUtil()
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
|
||||
onComplete(imageKnifeData)
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap)
|
||||
}
|
||||
parseImageUtil.parseImage(arraybuffer, success, onError)
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import {LogUtil} from '../../imageknife/utils/LogUtil'
|
|||
import resourceManager from '@ohos.resourceManager';
|
||||
import image from "@ohos.multimedia.image"
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import { GIFFrame } from '../utils/gif/GIFFrame'
|
||||
|
||||
export class PlaceHolderManager<T> {
|
||||
private options: RequestOption;
|
||||
|
||||
|
@ -32,21 +34,16 @@ export class PlaceHolderManager<T> {
|
|||
this.options = option;
|
||||
}
|
||||
|
||||
static execute(option: RequestOption) {
|
||||
let manager:PlaceHolderManager<ImageKnifeData> = new PlaceHolderManager<ImageKnifeData>(option);
|
||||
return new Promise(manager.process)
|
||||
.then(option.placeholderOnComplete).catch(option.placeholderOnError);
|
||||
}
|
||||
|
||||
process = (onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
process = (onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
this.displayPlaceholder(onComplete, onError);
|
||||
}
|
||||
|
||||
private displayPlaceholder(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void){
|
||||
LogUtil.log("displayPlaceholder")
|
||||
private displayPlaceholder(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void){
|
||||
LogUtil.log("ImageKnife displayPlaceholder")
|
||||
if ((typeof (this.options.placeholderSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, this.options.placeholderSrc as PixelMap)
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap);
|
||||
} else if (typeof this.options.placeholderSrc == 'string') {
|
||||
|
||||
} else {
|
||||
|
@ -87,16 +84,16 @@ export class PlaceHolderManager<T> {
|
|||
|
||||
|
||||
|
||||
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
private svgProcess(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
let svgParseImpl:SVGParseImpl = new SVGParseImpl()
|
||||
svgParseImpl.parseSvg(this.options,arraybuffer, onComplete,onError);
|
||||
}
|
||||
|
||||
private mediaImageProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
private mediaImageProcess(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
let parseImageUtil:ParseImageUtil = new ParseImageUtil()
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
|
||||
onComplete(imageKnifeData)
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap)
|
||||
}
|
||||
parseImageUtil.parseImage(arraybuffer, success, onError)
|
||||
}
|
||||
|
|
|
@ -32,21 +32,15 @@ export class RetryHolderManager<T> {
|
|||
this.options = option;
|
||||
}
|
||||
|
||||
static execute(option: RequestOption) {
|
||||
let manager:RetryHolderManager<ImageKnifeData> = new RetryHolderManager<ImageKnifeData>(option);
|
||||
return new Promise(manager.process)
|
||||
.then(option.retryholderOnComplete).catch(option.retryholderOnError);
|
||||
}
|
||||
|
||||
process = (onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
process = (onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
this.displayRetryholder(onComplete, onError);
|
||||
}
|
||||
|
||||
private displayRetryholder(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void){
|
||||
LogUtil.log("displayRetryholder")
|
||||
private displayRetryholder(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void){
|
||||
LogUtil.log("ImageKnife displayRetryholder")
|
||||
if ((typeof (this.options.retryholderSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, this.options.placeholderSrc as PixelMap)
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap);
|
||||
} else if (typeof this.options.placeholderSrc == 'string') {
|
||||
|
||||
} else {
|
||||
|
@ -87,16 +81,16 @@ export class RetryHolderManager<T> {
|
|||
|
||||
|
||||
|
||||
private svgProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
private svgProcess(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
let svgParseImpl = new SVGParseImpl()
|
||||
svgParseImpl.parseSvg(this.options,arraybuffer, onComplete,onError);
|
||||
}
|
||||
|
||||
private mediaImageProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
private mediaImageProcess(onComplete:(value:PixelMap)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string) {
|
||||
let parseImageUtil = new ParseImageUtil()
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
|
||||
onComplete(imageKnifeData)
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap)
|
||||
}
|
||||
parseImageUtil.parseImage(arraybuffer, success, onError)
|
||||
}
|
||||
|
|
|
@ -13,24 +13,18 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { IDataFetch } from '../networkmanage/IDataFetch'
|
||||
import { IDataFetch } from '../networkmanage/IDataFetch'
|
||||
import { RequestOption } from '../RequestOption'
|
||||
import { SparkMD5 } from '../../3rd_party/sparkmd5/spark-md5'
|
||||
import { FileUtils } from '../../cache/FileUtils'
|
||||
import loadRequest from '@ohos.request';
|
||||
import { LogUtil } from '../utils/LogUtil'
|
||||
import { ImageKnifeGlobal } from '../ImageKnifeGlobal'
|
||||
import common from '@ohos.app.ability.common'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import http from '@ohos.net.http'
|
||||
|
||||
// 数据加载器
|
||||
class RequestData{
|
||||
class RequestData {
|
||||
receiveSize: number = 2000
|
||||
totalSize: number = 2000
|
||||
}
|
||||
|
||||
export class HttpDownloadClient implements IDataFetch {
|
||||
loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) {
|
||||
async loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) {
|
||||
try {
|
||||
let httpRequest = http.createHttp()
|
||||
let arrayBuffers = new Array<ArrayBuffer>();
|
||||
|
@ -47,7 +41,7 @@ export class HttpDownloadClient implements IDataFetch {
|
|||
})
|
||||
httpRequest.on('dataReceiveProgress', (data: RequestData) => {
|
||||
// 下载进度
|
||||
if(data != undefined && (typeof data.receiveSize == 'number') && (typeof data.totalSize == 'number') ) {
|
||||
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)
|
||||
|
@ -64,28 +58,26 @@ export class HttpDownloadClient implements IDataFetch {
|
|||
request.headers.forEach((value, key) => {
|
||||
headerObj[key] = value
|
||||
})
|
||||
httpRequest.requestInStream(
|
||||
request.loadSrc as string,
|
||||
{
|
||||
header: headerObj,
|
||||
method: http.RequestMethod.GET,
|
||||
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
||||
connectTimeout: 60000, // 可选 默认60000ms
|
||||
readTimeout: 0, // 可选, 默认为60000ms
|
||||
usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定
|
||||
usingCache: false
|
||||
}
|
||||
).then((data)=>{
|
||||
if(data == 200) {
|
||||
let promise = httpRequest.requestInStream(request.loadSrc as string, {
|
||||
header: headerObj,
|
||||
method: http.RequestMethod.GET,
|
||||
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
||||
connectTimeout: 60000, // 可选 默认60000ms
|
||||
readTimeout: 0, // 可选, 默认为60000ms
|
||||
usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定
|
||||
usingCache: false
|
||||
});
|
||||
await promise.then((data) => {
|
||||
if (data == 200) {
|
||||
|
||||
} else {
|
||||
onError(`HttpDownloadClient has error, http code = ${data}`)
|
||||
}
|
||||
}).catch((err:Error)=>{
|
||||
}).catch((err: Error) => {
|
||||
onError(`HttpDownloadClient has error, http code = ${err}`)
|
||||
})
|
||||
} catch (err) {
|
||||
onError('HttpDownloadClient catch err request uuid ='+request.uuid)
|
||||
onError('HttpDownloadClient catch err request uuid =' + request.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
import { ICache } from "../requestmanage/ICache"
|
||||
import { DiskLruCache } from "@ohos/disklrucache"
|
||||
import { DiskLruCache } from "../../cache/disklrucache"
|
||||
|
||||
export class DiskCacheProxy implements ICache<string, ArrayBuffer> {
|
||||
private mDiskLruCache: DiskLruCache;
|
||||
|
@ -38,7 +38,7 @@ export class DiskCacheProxy implements ICache<string, ArrayBuffer> {
|
|||
}
|
||||
|
||||
getValue(key: string): ArrayBuffer{
|
||||
return this.mDiskLruCache.get(key);
|
||||
return this.mDiskLruCache.get(key) as ArrayBuffer;
|
||||
}
|
||||
|
||||
putValue(key: string, value: ArrayBuffer) {
|
||||
|
|
|
@ -13,25 +13,26 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { RequestOption,Size } from '../../imageknife/RequestOption'
|
||||
import { DiskLruCache } from '@ohos/disklrucache'
|
||||
import { RequestOption, Size } from '../../imageknife/RequestOption'
|
||||
import { DiskLruCache } from "../../cache/DiskLruCache"
|
||||
import { LruCache } from '../../cache/LruCache'
|
||||
import { SparkMD5 } from '../../3rd_party/sparkmd5/spark-md5'
|
||||
import { MemoryCacheProxy } from '../requestmanage/MemoryCacheProxy'
|
||||
import { DiskCacheProxy } from '../requestmanage/DiskCacheProxy'
|
||||
import { FileTypeUtil } from '../utils/FileTypeUtil'
|
||||
import { IDataFetch } from '../../imageknife/networkmanage/IDataFetch'
|
||||
import { IResourceFetch } from '../../imageknife/resourcemanage/IResourceFetch'
|
||||
import { IDataFetch } from '../../imageknife/networkmanage/IDataFetch'
|
||||
import { IResourceFetch } from '../../imageknife/resourcemanage/IResourceFetch'
|
||||
import { ImageKnifeData, ImageKnifeType } from '../ImageKnifeData'
|
||||
import { AllCacheInfo } from '../../imageknife/interface/IAllCacheInfoCallback'
|
||||
import { ParseImageUtil } from '../utils/ParseImageUtil'
|
||||
import { IParseImage } from '../interface/IParseImage'
|
||||
import { IParseImage } from '../interface/IParseImage'
|
||||
import image from '@ohos.multimedia.image'
|
||||
import { SVGParseImpl } from '../utils/svg/SVGParseImpl'
|
||||
import { GIFParseImpl } from '../utils/gif/GIFParseImpl'
|
||||
import { GIFFrame } from '../utils/gif/GIFFrame'
|
||||
import { LogUtil } from '../../imageknife/utils/LogUtil'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import taskpool from '@ohos.taskpool';
|
||||
|
||||
|
||||
export enum Stage {
|
||||
|
@ -62,19 +63,13 @@ export enum RunReason {
|
|||
export class RequestManager {
|
||||
private TAG: string = "RequestManager";
|
||||
private options: RequestOption;
|
||||
private mMemoryCacheProxy: MemoryCacheProxy<string, ImageKnifeData>;
|
||||
private mDiskCacheProxy: DiskCacheProxy;
|
||||
private mIDataFetch: IDataFetch;
|
||||
private mIResourceFetch: IResourceFetch<ArrayBuffer>;
|
||||
private mParseImageUtil: IParseImage<PixelMap>;
|
||||
|
||||
constructor(option: RequestOption, memoryCache1: LruCache<string, ImageKnifeData>, diskMemoryCache1: DiskLruCache, dataFetch: IDataFetch, resourceFetch: IResourceFetch<ArrayBuffer>) {
|
||||
constructor(option: RequestOption, dataFetch: IDataFetch, resourceFetch: IResourceFetch<ArrayBuffer>) {
|
||||
this.options = option;
|
||||
|
||||
// 缓存部分
|
||||
this.mMemoryCacheProxy = new MemoryCacheProxy(memoryCache1);
|
||||
this.mDiskCacheProxy = new DiskCacheProxy(diskMemoryCache1);
|
||||
|
||||
// 网络下载能力
|
||||
this.mIDataFetch = dataFetch;
|
||||
|
||||
|
@ -85,63 +80,16 @@ export class RequestManager {
|
|||
this.mParseImageUtil = new ParseImageUtil();
|
||||
}
|
||||
|
||||
static execute(option: RequestOption, memoryCache1: LruCache<string, ImageKnifeData>, diskMemoryCache1: DiskLruCache, dataFetch: IDataFetch, resourceFetch: IResourceFetch<ArrayBuffer>) {
|
||||
LogUtil.log("RequestManager execute")
|
||||
let manager = new RequestManager(option, memoryCache1, diskMemoryCache1, dataFetch, resourceFetch);
|
||||
return new Promise<ImageKnifeData>(manager.process)
|
||||
.then(option.loadComplete)
|
||||
.then(manager.loadCompleteAfter)
|
||||
.catch(option.loadError);
|
||||
}
|
||||
|
||||
loadCompleteAfter =()=>{
|
||||
try { // 内部消化问题
|
||||
LogUtil.log("loadCompleteAfter!")
|
||||
if (this.options.allCacheInfoCallback) {
|
||||
LogUtil.log("RequestOption =" + JSON.stringify(this.options));
|
||||
|
||||
// 内存缓存
|
||||
let allCacheInfo:AllCacheInfo = {
|
||||
memoryCacheInfo:{key:'', data:new ImageKnifeData()},
|
||||
resourceCacheInfo:{key:'', path:''},
|
||||
dataCacheInfo:{key:'',path:''}
|
||||
};
|
||||
let memoryCache = this.mMemoryCacheProxy.getValue(this.options.generateCacheKey);
|
||||
allCacheInfo.memoryCacheInfo = {
|
||||
key: this.options.generateCacheKey,
|
||||
data: memoryCache
|
||||
}
|
||||
|
||||
// 变换后缓存
|
||||
allCacheInfo.resourceCacheInfo = {
|
||||
key: SparkMD5.hashBinary(this.options.generateResourceKey) as string,
|
||||
path: (this.mDiskCacheProxy.getCachePath() + SparkMD5.hashBinary(this.options.generateResourceKey)) as string
|
||||
};
|
||||
|
||||
// 原图缓存
|
||||
allCacheInfo.dataCacheInfo = {
|
||||
key: SparkMD5.hashBinary(this.options.generateDataKey) as string,
|
||||
path: (this.mDiskCacheProxy.getCachePath() + SparkMD5.hashBinary(this.options.generateDataKey)) as string
|
||||
}
|
||||
this.options.allCacheInfoCallback.callback(allCacheInfo)
|
||||
}
|
||||
} catch (err) {
|
||||
LogUtil.log("after err =" + err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// DecodeJob work
|
||||
private mStage: Stage = Stage.INITIALIZE;
|
||||
private mRunReason: RunReason = RunReason.INITIALIZE;
|
||||
|
||||
process = (onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void)=>{
|
||||
LogUtil.log("RequestManager process !");
|
||||
process = (onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) => {
|
||||
LogUtil.log("ImageKnife RequestManager process !");
|
||||
this.loadLeve1MemoryCache(onComplete, onError)
|
||||
}
|
||||
|
||||
private runWrapped(request: RequestOption, runReason: RunReason, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager runWrapped")
|
||||
private runWrapped(request: RequestOption, runReason: RunReason, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager runWrapped")
|
||||
if (runReason == RunReason.INITIALIZE) {
|
||||
this.mStage = this.getNextStage(request, this.mStage);
|
||||
this.searchLoadFrom(this.options, this.mStage, onComplete, onError);
|
||||
|
@ -150,7 +98,7 @@ export class RequestManager {
|
|||
}
|
||||
}
|
||||
|
||||
private getNextStage(request: RequestOption, current: Stage): Stage{
|
||||
private getNextStage(request: RequestOption, current: Stage): Stage {
|
||||
if (current == Stage.INITIALIZE) {
|
||||
return request.strategy.decodeCachedResource()
|
||||
? Stage.RESOURCE_CACHE
|
||||
|
@ -166,13 +114,13 @@ export class RequestManager {
|
|||
} else if (current == Stage.FINISHED) {
|
||||
return Stage.FINISHED;
|
||||
} else {
|
||||
throw new Error("Unrecognized stage: " + current);
|
||||
throw new Error("ImageKnife Unrecognized stage: " + current);
|
||||
}
|
||||
}
|
||||
|
||||
// 究竟从哪里加载数据
|
||||
private searchLoadFrom(request: RequestOption, current: Stage, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager searchLoadFrom")
|
||||
private searchLoadFrom(request: RequestOption, current: Stage, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager searchLoadFrom")
|
||||
if (current == Stage.RESOURCE_CACHE) {
|
||||
this.loadDiskFromTransform(request, onComplete, onError);
|
||||
} else if (current == Stage.DATA_CACHE) {
|
||||
|
@ -187,73 +135,73 @@ export class RequestManager {
|
|||
}
|
||||
|
||||
// 加载网络资源
|
||||
private loadSourceFromNetwork(request: RequestOption, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
let success = (arraybuffer:ArrayBuffer) => {
|
||||
this.downloadSuccess(request,arraybuffer, onComplete, onError)
|
||||
private loadSourceFromNetwork(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
try {
|
||||
LogUtil.log("ImageKnife RequestManager loadSourceFromNetwork")
|
||||
let success = (arraybuffer: ArrayBuffer) => {
|
||||
this.downloadSuccess(request, arraybuffer, onComplete, onError)
|
||||
}
|
||||
let error = (errorMsg:string) =>{
|
||||
let error = (errorMsg: string) => {
|
||||
onError(errorMsg)
|
||||
}
|
||||
this.mIDataFetch.loadData(request, success, error);
|
||||
} catch (e) {
|
||||
LogUtil.error("ImageKnife RequestManager loadSourceFromNetwork error")
|
||||
}
|
||||
}
|
||||
|
||||
// 加载本地资源
|
||||
private loadSourceFormNative(request: RequestOption, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager loadSourceFormNative")
|
||||
private loadSourceFormNative(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager loadSourceFormNative")
|
||||
// 本地解析后进行一级缓存
|
||||
let success = (arrayBuffer:ArrayBuffer) => {
|
||||
let success = (arrayBuffer: ArrayBuffer) => {
|
||||
// 使用媒体子系统 ImageSource解析文件 获取PixelMap
|
||||
let fileTypeUtil = new FileTypeUtil();
|
||||
let typeValue = fileTypeUtil.getFileType(arrayBuffer)
|
||||
LogUtil.log("RequestManager - 文件类型为= " + typeValue)
|
||||
LogUtil.log("ImageKnife RequestManager - 文件类型为= " + typeValue)
|
||||
// gif处理
|
||||
if(ImageKnifeData.GIF == typeValue && !request.dontAnimateFlag){
|
||||
if (ImageKnifeData.GIF == typeValue && !request.dontAnimateFlag) {
|
||||
// 处理gif
|
||||
this.gifProcess(onComplete,onError, arrayBuffer,typeValue,(imageKnifeData)=>{
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
|
||||
})
|
||||
}else if(ImageKnifeData.SVG == typeValue){
|
||||
this.gifProcess(onComplete, onError, arrayBuffer, typeValue)
|
||||
} else if (ImageKnifeData.SVG == typeValue) {
|
||||
// 处理svg
|
||||
this.svgProcess(request,onComplete,onError,arrayBuffer,typeValue,(imageKnifeData)=>{
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey,imageKnifeData)
|
||||
})
|
||||
this.svgProcess(request, onComplete, onError, arrayBuffer, typeValue)
|
||||
} else {
|
||||
if (request.transformations[0]) {
|
||||
request.transformations[0].transform(arrayBuffer, request, {asyncTransform:(error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
// 输出给Image
|
||||
if (pixelMap) {
|
||||
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap);
|
||||
this.mMemoryCacheProxy.putValue(request.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
} else {
|
||||
onError(error);
|
||||
request.transformations[0].transform(arrayBuffer, request, {
|
||||
asyncTransform: (error: BusinessError | string, pixelMap: PixelMap | null) => {
|
||||
// 输出给Image
|
||||
if (pixelMap) {
|
||||
onComplete(pixelMap);
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}
|
||||
}})
|
||||
})
|
||||
}
|
||||
else {
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
this.mMemoryCacheProxy.putValue(request.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImage(arrayBuffer, success, onError)
|
||||
}
|
||||
}
|
||||
}
|
||||
let ctx = request.getModuleContext();
|
||||
if(ctx!=undefined){
|
||||
this.mIResourceFetch.loadResource(ctx,request.loadSrc as Resource, success, onError);
|
||||
}else{
|
||||
onError('RequestManager loadSourceFormNative moduleContext is undefined! please check it')
|
||||
if (ctx != undefined) {
|
||||
this.mIResourceFetch.loadResource(ctx, request.loadSrc as Resource, success, onError);
|
||||
} else {
|
||||
onError('ImageKnife RequestManager loadSourceFormNative moduleContext is undefined! please check it')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 加载磁盘缓存 原图
|
||||
private loadDiskFromSource(request: RequestOption, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager loadDiskFromSource")
|
||||
let cached = this.mDiskCacheProxy.getValue(request.generateDataKey)
|
||||
private loadDiskFromSource(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager loadDiskFromSource")
|
||||
let cached = DiskLruCache.getFileCacheByFile(request?.moduleContext?.filesDir as string, request.generateDataKey);
|
||||
if (cached != null && cached.byteLength > 0) {
|
||||
LogUtil.log("ImageKnife loadDiskFromSource load resource from DiskLruCache")
|
||||
this.parseDiskFile2PixelMap(request, cached, onComplete, onError)
|
||||
} else {
|
||||
this.mStage = Stage.SOURCE;
|
||||
|
@ -262,10 +210,11 @@ export class RequestManager {
|
|||
}
|
||||
|
||||
// 加载磁盘缓存 变换后图片
|
||||
private loadDiskFromTransform(request: RequestOption, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager loadDiskFromTransform")
|
||||
let cached = this.mDiskCacheProxy.getValue(request.generateResourceKey)
|
||||
private loadDiskFromTransform(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager loadDiskFromTransform")
|
||||
let cached = DiskLruCache.getFileCacheByFile(request.moduleContext?.filesDir as string, request.generateResourceKey);
|
||||
if (cached != null) {
|
||||
LogUtil.log("ImageKnife loadDiskFromTransform load resource from DiskLruCache")
|
||||
this.parseDiskTransformFile2PixelMap(request, cached, onComplete, onError)
|
||||
} else {
|
||||
this.mStage = Stage.DATA_CACHE;
|
||||
|
@ -273,103 +222,95 @@ export class RequestManager {
|
|||
}
|
||||
}
|
||||
|
||||
parseSource(request: RequestOption, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager parseSource")
|
||||
parseSource(request: RequestOption, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager parseSource")
|
||||
try {
|
||||
if ((typeof (request.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||
// PixelMap 外层捕获效率更高,不会进入这里
|
||||
} else if (typeof request.loadSrc == 'string') {
|
||||
this.loadSourceFromNetwork(request, onComplete, onError);
|
||||
} else {
|
||||
let res = request.loadSrc as Resource;
|
||||
if (typeof res.id != 'undefined' && typeof res.id != 'undefined') {
|
||||
if (typeof res.id != 'undefined') {
|
||||
this.loadSourceFormNative(request, onComplete, onError)
|
||||
} else {
|
||||
LogUtil.log("输入参数有问题!")
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
LogUtil.error("ImageKnife RequestManager parseSource error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private loadLeve1MemoryCache(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log("RequestManager loadLeve1MemoryCache")
|
||||
// 一级缓存 内存获取
|
||||
let cache = this.mMemoryCacheProxy.loadMemoryCache(this.options.generateCacheKey, this.options.isCacheable);
|
||||
if (cache == null || typeof cache == 'undefined') {
|
||||
// 处理磁盘加载 网络加载
|
||||
private loadLeve1MemoryCache(onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
try {
|
||||
this.runWrapped(this.options, this.mRunReason, onComplete, onError)
|
||||
} else {
|
||||
// 需要清理状态
|
||||
cache.waitSaveDisk = false;
|
||||
onComplete(cache);
|
||||
return
|
||||
|
||||
} catch (e) {
|
||||
LogUtil.error("ImageKnife loadLeve1MemoryCache error")
|
||||
}
|
||||
}
|
||||
|
||||
// 解析磁盘文件变成PixeMap
|
||||
private parseDiskFile2PixelMap(request: RequestOption, source: ArrayBuffer, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
private parseDiskFile2PixelMap(request: RequestOption, source: ArrayBuffer, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager parseDiskFile2PixelMap")
|
||||
// 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||
let fileTypeUtil = new FileTypeUtil();
|
||||
let typeValue = fileTypeUtil.getFileType(source);
|
||||
// 解析磁盘文件 gif 和 svg
|
||||
if(ImageKnifeData.GIF == typeValue && !request.dontAnimateFlag){
|
||||
if (ImageKnifeData.GIF == typeValue && !request.dontAnimateFlag) {
|
||||
// 处理gif
|
||||
this.gifProcess(onComplete,onError,source,typeValue, (imageKnifeData)=>{
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
|
||||
})
|
||||
}else if(ImageKnifeData.SVG == typeValue){
|
||||
this.svgProcess(request,onComplete,onError, source, typeValue, (imageKnifeData)=>{
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
|
||||
})
|
||||
this.gifProcess(onComplete, onError, source, typeValue)
|
||||
} else if (ImageKnifeData.SVG == typeValue) {
|
||||
this.svgProcess(request, onComplete, onError, source, typeValue)
|
||||
} else {
|
||||
if (this.options.transformations[0]) {
|
||||
if (this.options.thumbSizeMultiplier) {
|
||||
let thumbOption:RequestOption = new RequestOption();
|
||||
let thumbOption: RequestOption = new RequestOption();
|
||||
thumbOption.setImageViewSize({
|
||||
width: Math.round(this.options.thumbSizeMultiplier * this.options.size.width),
|
||||
height: Math.round(this.options.thumbSizeMultiplier * this.options.size.height)
|
||||
})
|
||||
let ctx = this.options.getModuleContext()
|
||||
if(ctx != undefined){
|
||||
if (ctx != undefined) {
|
||||
thumbOption.setModuleContext(ctx)
|
||||
}else{
|
||||
} else {
|
||||
onError('RequestManager parseDiskFile2PixelMap moduleContext is undefined, please check it!')
|
||||
return
|
||||
}
|
||||
let thumbCallback = this.options.thumbholderOnComplete;
|
||||
let thumbError = this.options.thumbholderOnError;
|
||||
this.options.transformations[0].transform(source, thumbOption,{asyncTransform: (error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
if (pixelMap) {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap);
|
||||
thumbCallback(imageKnifeData);
|
||||
} else {
|
||||
thumbError(error);
|
||||
}
|
||||
}})
|
||||
setTimeout(()=>{
|
||||
this.options.transformations[0].transform(source, request, {asyncTransform: (error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
this.options.transformations[0].transform(source, thumbOption, {
|
||||
asyncTransform: (error: BusinessError | string, pixelMap: PixelMap | null) => {
|
||||
if (pixelMap) {
|
||||
// 保存一份变换后的图片PixelMap到MemoryCache
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap);
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
thumbCallback(pixelMap);
|
||||
} else {
|
||||
thumbError(error);
|
||||
}
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.options.transformations[0].transform(source, request, {
|
||||
asyncTransform: (error: BusinessError | string, pixelMap: PixelMap | null) => {
|
||||
if (pixelMap) {
|
||||
onComplete(pixelMap);
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}
|
||||
})
|
||||
}, this.options.thumbDelayTime);
|
||||
}
|
||||
else {
|
||||
this.options.transformations[0].transform(source, request, {
|
||||
asyncTransform: (error: BusinessError | string, pixelMap: PixelMap | null) => {
|
||||
if (pixelMap) {
|
||||
onComplete(pixelMap);
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}})
|
||||
},this.options.thumbDelayTime);
|
||||
}
|
||||
else {
|
||||
this.options.transformations[0].transform(source, request, {asyncTransform: (error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
if (pixelMap) {
|
||||
// 保存一份变换后的图片PixelMap到MemoryCache
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap);
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// thumbnail 缩略图部分
|
||||
|
@ -377,24 +318,18 @@ export class RequestManager {
|
|||
let thumbCallback = this.options.thumbholderOnComplete
|
||||
let thumbError = this.options.thumbholderOnError
|
||||
let thumbSuccess = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
thumbCallback(imageKnifeData);
|
||||
thumbCallback(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImageThumbnail(request.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||
setTimeout(()=>{
|
||||
setTimeout(() => {
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
},this.options.thumbDelayTime)
|
||||
}
|
||||
else {
|
||||
onComplete(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
}, this.options.thumbDelayTime)
|
||||
} else {
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
}
|
||||
|
@ -403,7 +338,8 @@ export class RequestManager {
|
|||
}
|
||||
|
||||
// 解析磁盘变换后文件变成PixeMap
|
||||
private parseDiskTransformFile2PixelMap(request: RequestOption, source: ArrayBuffer, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
private parseDiskTransformFile2PixelMap(request: RequestOption, source: ArrayBuffer, onComplete: (value: PixelMap) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ImageKnife RequestManager parseDiskTransformFile2PixelMap")
|
||||
let fileTypeUtil = new FileTypeUtil();
|
||||
let typeValue = fileTypeUtil.getFileType(source);
|
||||
// thumbnail 缩略图部分
|
||||
|
@ -411,33 +347,27 @@ export class RequestManager {
|
|||
let thumbCallback = this.options.thumbholderOnComplete
|
||||
let thumbError = this.options.thumbholderOnError
|
||||
let thumbSuccess = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
thumbCallback(imageKnifeData);
|
||||
thumbCallback(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImageThumbnail(request.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||
setTimeout(()=>{
|
||||
setTimeout(() => {
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
},this.options.thumbDelayTime)
|
||||
}else{
|
||||
}, this.options.thumbDelayTime)
|
||||
} else {
|
||||
let success = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value)
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImage(source, success, onError)
|
||||
}
|
||||
}
|
||||
|
||||
private downloadSuccess(request: RequestOption,source: ArrayBuffer, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void) {
|
||||
LogUtil.log('Download task completed.');
|
||||
private downloadSuccess(request: RequestOption, source: ArrayBuffer, onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
|
||||
if(source == null || source == undefined || source.byteLength <= 0){
|
||||
onError('Download task completed. but download file is empty!')
|
||||
if (source == null || source == undefined || source.byteLength <= 0) {
|
||||
onError('ImageKnife Download task completed. but download file is empty!')
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -446,8 +376,8 @@ export class RequestManager {
|
|||
// 步骤二: 文件名保存一份全局
|
||||
// 步骤三:查看文件是否支持 非支持类型直接返回
|
||||
let fileTypeUtil = new FileTypeUtil();
|
||||
let filetype:string|null = fileTypeUtil.getFileType(source);
|
||||
if(filetype == null){
|
||||
let filetype: string | null = fileTypeUtil.getFileType(source);
|
||||
if (filetype == null) {
|
||||
onError("下载文件解析后类型为null,请检查数据源!");
|
||||
return;
|
||||
}
|
||||
|
@ -458,52 +388,50 @@ export class RequestManager {
|
|||
}
|
||||
|
||||
// 解析磁盘文件 gif 和 svg
|
||||
if(ImageKnifeData.GIF == filetype && !this.options.dontAnimateFlag){
|
||||
if (ImageKnifeData.GIF == filetype && !this.options.dontAnimateFlag) {
|
||||
// 处理gif
|
||||
this.gifProcess(onComplete,onError,source,filetype, (imageKnifeData)=>{
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
|
||||
})
|
||||
this.gifProcess(onComplete, onError, source, filetype)
|
||||
|
||||
// 保存二级磁盘缓存
|
||||
Promise.resolve(source)
|
||||
.then((arraybuffer: ArrayBuffer)=>{
|
||||
this.mDiskCacheProxy.putValue(this.options.generateDataKey, arraybuffer)
|
||||
.then((arraybuffer: ArrayBuffer) => {
|
||||
DiskLruCache.saveFileCacheOnlyFile(this.options.moduleContext?.filesDir as string, this.options.generateDataKey,arraybuffer);
|
||||
})
|
||||
.catch( (err:BusinessError)=>{
|
||||
LogUtil.log('download file is ='+ImageKnifeData.GIF+'and save diskLruCache error ='+ (err as BusinessError))
|
||||
.catch((err: BusinessError) => {
|
||||
LogUtil.log('download file is =' + ImageKnifeData.GIF + 'and save diskLruCache error =' + (err as BusinessError))
|
||||
})
|
||||
}else if(ImageKnifeData.SVG == filetype){
|
||||
} else if (ImageKnifeData.SVG == filetype) {
|
||||
// 处理svg
|
||||
this.svgProcess(request,onComplete,onError, source, filetype, (imageKnifeData)=>{
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData)
|
||||
})
|
||||
this.svgProcess(request, onComplete, onError, source, filetype)
|
||||
|
||||
// 保存二级磁盘缓存
|
||||
Promise.resolve(source)
|
||||
.then((arraybuffer: ArrayBuffer)=>{
|
||||
this.mDiskCacheProxy.putValue(this.options.generateDataKey, arraybuffer)
|
||||
.then((arraybuffer: ArrayBuffer) => {
|
||||
DiskLruCache.saveFileCacheOnlyFile(this.options.moduleContext?.filesDir as string, this.options.generateDataKey,arraybuffer);
|
||||
})
|
||||
.catch((err:BusinessError)=>{
|
||||
LogUtil.log('download file is ='+ImageKnifeData.SVG+'and save diskLruCache error ='+ (err as BusinessError))
|
||||
.catch((err: BusinessError) => {
|
||||
LogUtil.log('download file is =' + ImageKnifeData.SVG + 'and save diskLruCache error =' + (err as BusinessError))
|
||||
})
|
||||
} else {
|
||||
// 进行变换
|
||||
if (this.options.transformations[0]) {
|
||||
// thumbnail 缩略图部分
|
||||
if (this.options.thumbSizeMultiplier) {
|
||||
if(filetype != null) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// thumbnail 缩略图部分
|
||||
|
@ -511,13 +439,12 @@ export class RequestManager {
|
|||
let thumbCallback = this.options.thumbholderOnComplete
|
||||
let thumbError = this.options.thumbholderOnError
|
||||
let thumbSuccess = (value: PixelMap) => {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
thumbCallback(imageKnifeData);
|
||||
thumbCallback(value);
|
||||
}
|
||||
this.mParseImageUtil.parseImageThumbnail(this.options.thumbSizeMultiplier, source, thumbSuccess, thumbError);
|
||||
setTimeout(() => {
|
||||
let success = (value: PixelMap) => {
|
||||
if(filetype != null) {
|
||||
if (filetype != null) {
|
||||
this.saveCacheAndDisk(value, filetype, onComplete, source);
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +452,7 @@ export class RequestManager {
|
|||
}, this.options.thumbDelayTime)
|
||||
} else {
|
||||
let success = (value: PixelMap) => {
|
||||
if(filetype != null) {
|
||||
if (filetype != null) {
|
||||
this.saveCacheAndDisk(value, filetype, onComplete, source);
|
||||
}
|
||||
}
|
||||
|
@ -535,94 +462,90 @@ export class RequestManager {
|
|||
}
|
||||
}
|
||||
|
||||
createImagePixelMap(imageKnifeType: ImageKnifeType, imageKnifeValue: PixelMap): ImageKnifeData{
|
||||
return ImageKnifeData.createImagePixelMap(imageKnifeType,imageKnifeValue);
|
||||
createImagePixelMap(imageKnifeType: ImageKnifeType, imageKnifeValue: PixelMap): ImageKnifeData {
|
||||
return ImageKnifeData.createImagePixelMap(imageKnifeType, imageKnifeValue);
|
||||
}
|
||||
|
||||
createImageGIFFrame(imageKnifeType: ImageKnifeType, imageKnifeValue: GIFFrame[]): ImageKnifeData{
|
||||
return ImageKnifeData.createImageGIFFrame(imageKnifeType,imageKnifeValue);
|
||||
createImageGIFFrame(imageKnifeType: ImageKnifeType, imageKnifeValue: GIFFrame[]): ImageKnifeData {
|
||||
return ImageKnifeData.createImageGIFFrame(imageKnifeType, imageKnifeValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private saveCacheAndDisk(value: PixelMap, filetype:string, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, source:ArrayBuffer) {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, value);
|
||||
this.mMemoryCacheProxy.putValue(this.options.generateCacheKey, imageKnifeData);
|
||||
let save2DiskCache = (arraybuffer:ArrayBuffer) => {
|
||||
this.mDiskCacheProxy.putValue(this.options.generateDataKey, arraybuffer)
|
||||
private async saveCacheAndDisk(value: PixelMap, filetype: string, onComplete: (value: PixelMap) => void | PromiseLike<ImageKnifeData>, source: ArrayBuffer) {
|
||||
let save2DiskCache = (arraybuffer: ArrayBuffer) => {
|
||||
DiskLruCache.saveFileCacheOnlyFile(this.options.moduleContext?.filesDir as string, this.options.generateDataKey,arraybuffer);
|
||||
// 落盘之后需要主动移除当前request并且调用下一个加载
|
||||
let removeCurrentAndSearchNextRun = this.options.removeCurrentAndSearchNext
|
||||
removeCurrentAndSearchNextRun();
|
||||
}
|
||||
let runSave2Disk = (resolve:(value:ArrayBuffer)=>void|PromiseLike<ArrayBuffer>, reject:(reason?:BusinessError|string)=>void) => {
|
||||
let runSave2Disk = (resolve: (value: ArrayBuffer) => void | PromiseLike<ArrayBuffer>, reject: (reason?: BusinessError | string) => void) => {
|
||||
resolve(source);
|
||||
}
|
||||
let promise = new Promise(runSave2Disk);
|
||||
promise.then(save2DiskCache);
|
||||
imageKnifeData.waitSaveDisk = true;
|
||||
onComplete(imageKnifeData);
|
||||
await promise.then(save2DiskCache);
|
||||
onComplete(value);
|
||||
}
|
||||
|
||||
thumbnailProcess(source:ArrayBuffer, filetype:string, onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void){
|
||||
thumbnailProcess(source: ArrayBuffer, filetype: string, onComplete: (value: PixelMap) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void) {
|
||||
let thumbOption = new RequestOption();
|
||||
let ctx = this.options.getModuleContext()
|
||||
if(ctx != undefined){
|
||||
if (ctx != undefined) {
|
||||
thumbOption.setModuleContext(ctx)
|
||||
}else{
|
||||
} else {
|
||||
onError('RequestManager thumbnailProcess moduleContext is undefined, please check it!')
|
||||
return
|
||||
}
|
||||
thumbOption.setImageViewSize({
|
||||
width: Math.round(this.options.thumbSizeMultiplier * this.options.size.width),
|
||||
height: Math.round(this.options.thumbSizeMultiplier * this.options.size.height)
|
||||
})
|
||||
})
|
||||
let thumbCallback = this.options.thumbholderOnComplete
|
||||
let thumbError = this.options.thumbholderOnError
|
||||
this.options.transformations[0].transform(source, thumbOption, {asyncTransform: (error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
if (pixelMap) {
|
||||
let imageKnifeData = this.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap);
|
||||
thumbCallback(imageKnifeData);
|
||||
} else {
|
||||
thumbError(error);
|
||||
}
|
||||
}})
|
||||
setTimeout(() => {
|
||||
this.options.transformations[0].transform(source, this.options,{asyncTransform: (error:BusinessError|string, pixelMap: PixelMap|null) => {
|
||||
this.options.transformations[0].transform(source, thumbOption, {
|
||||
asyncTransform: (error: BusinessError | string, pixelMap: PixelMap | null) => {
|
||||
if (pixelMap) {
|
||||
this.saveCacheAndDisk(pixelMap, filetype, onComplete, source);
|
||||
thumbCallback(pixelMap);
|
||||
} else {
|
||||
thumbError(error);
|
||||
}
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.options.transformations[0].transform(source, this.options, {
|
||||
asyncTransform: (error: BusinessError | string, pixelMap: PixelMap | null) => {
|
||||
if (pixelMap) {
|
||||
this.saveCacheAndDisk(pixelMap, filetype, onComplete, source);
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}})
|
||||
}, this.options.thumbDelayTime)
|
||||
}
|
||||
private svgProcess(option: RequestOption,onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {
|
||||
let svgParseImpl = new SVGParseImpl()
|
||||
svgParseImpl.parseSvg(option,arraybuffer, onComplete,onError)
|
||||
}
|
||||
})
|
||||
}, this.options.thumbDelayTime)
|
||||
}
|
||||
|
||||
private gifProcess(onComplete:(value:ImageKnifeData)=>void|PromiseLike<ImageKnifeData>, onError:(reason?:BusinessError|string)=>void, arraybuffer:ArrayBuffer, typeValue:string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {
|
||||
private svgProcess(option: RequestOption, onComplete: (value: PixelMap) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void, arraybuffer: ArrayBuffer, typeValue: string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {
|
||||
let svgParseImpl = new SVGParseImpl()
|
||||
svgParseImpl.parseSvg(option, arraybuffer, onComplete, onError)
|
||||
}
|
||||
|
||||
private gifProcess(onComplete: (value: PixelMap | GIFFrame[]) => void | PromiseLike<ImageKnifeData>, onError: (reason?: BusinessError | string) => void, arraybuffer: ArrayBuffer, typeValue: string, cacheStrategy?: (cacheData: ImageKnifeData) => void) {
|
||||
let gifParseImpl = new GIFParseImpl()
|
||||
gifParseImpl.parseGifs(arraybuffer, (data?:GIFFrame[],err?:BusinessError|string)=>{
|
||||
if(err){
|
||||
gifParseImpl.parseGifs(arraybuffer, (data?: GIFFrame[], err?: BusinessError | string) => {
|
||||
if (err) {
|
||||
onError(err)
|
||||
}
|
||||
LogUtil.log("gifProcess data is null:"+(data == null));
|
||||
if(!!data){
|
||||
let imageKnifeData = this.createImageGIFFrame(ImageKnifeType.GIFFRAME,data)
|
||||
LogUtil.log('gifProcess 生成gif 返回数据类型')
|
||||
if(cacheStrategy){
|
||||
LogUtil.log('gifProcess 生成gif并且存入了缓存策略')
|
||||
cacheStrategy(imageKnifeData)
|
||||
}
|
||||
onComplete(imageKnifeData)
|
||||
}else{
|
||||
LogUtil.log("gifProcess data is null:" + (data == null));
|
||||
if (!!data) {
|
||||
// let imageKnifeData = this.createImageGIFFrame(ImageKnifeType.GIFFRAME, data)
|
||||
// LogUtil.log('gifProcess 生成gif 返回数据类型')
|
||||
// if (cacheStrategy) {
|
||||
// LogUtil.log('gifProcess 生成gif并且存入了缓存策略')
|
||||
// cacheStrategy(imageKnifeData)
|
||||
// }
|
||||
onComplete(data)
|
||||
} else {
|
||||
onError('Parse GIF callback data is null, you need check callback data!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,5 +20,9 @@ export interface BaseTransform<T> {
|
|||
// 实现类 返回作为key生成的一部分
|
||||
getName(): string;
|
||||
|
||||
getClassName():string;
|
||||
|
||||
getConstructorParams():string;
|
||||
|
||||
transform(value: ArrayBuffer, request: RequestOption, func: AsyncTransform<T>):void;
|
||||
}
|
|
@ -37,6 +37,14 @@ export class BlurTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
|
||||
getClassName() {
|
||||
return "BlurTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams() {
|
||||
return JSON.stringify([this._mRadius,this.sampling]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "BlurTransformation _mRadius:" + this._mRadius +"==BlurTransformation sampling:"+ this.sampling;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,14 @@ export class BrightnessFilterTransformation implements BaseTransform<PixelMap> {
|
|||
this._mBrightness = brightness;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "BrightnessFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this._mBrightness]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "BrightnessFilterTransformation:" + this._mBrightness;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,15 @@ export class ContrastFilterTransformation implements BaseTransform<PixelMap> {
|
|||
this._mContrast = contrast;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "ContrastFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this._mContrast]);
|
||||
}
|
||||
|
||||
|
||||
getName() {
|
||||
return "ContrastFilterTransformation:" + this._mContrast;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,14 @@ export class CropCircleTransformation implements BaseTransform<PixelMap> {
|
|||
private mCenterY: number = 0;
|
||||
private mRadius: number = 0;
|
||||
|
||||
getClassName(){
|
||||
return "CropCircleTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return "[]";
|
||||
}
|
||||
|
||||
getName() {
|
||||
return CropCircleTransformation.TAG + ";mCenterX:" + this.mCenterX
|
||||
+ ";mCenterY:" + this.mCenterY
|
||||
|
|
|
@ -18,15 +18,17 @@ import { AsyncTransform } from "../transform/AsyncTransform"
|
|||
import { Constants } from "../constants/Constants"
|
||||
import { RequestOption } from "../../imageknife/RequestOption"
|
||||
import { TransformUtils } from "../transform/TransformUtils"
|
||||
import {LogUtil} from '../../imageknife/utils/LogUtil'
|
||||
import { LogUtil } from '../../imageknife/utils/LogUtil'
|
||||
import image from "@ohos.multimedia.image"
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import {Size} from '../../imageknife/RequestOption'
|
||||
export interface rgbColor{
|
||||
import { Size } from '../../imageknife/RequestOption'
|
||||
|
||||
export interface rgbColor {
|
||||
r_color: number,
|
||||
g_color: number,
|
||||
b_color: number,
|
||||
}
|
||||
|
||||
export class CropCircleWithBorderTransformation implements BaseTransform<PixelMap> {
|
||||
private static TAG: string = "CropCircleTransformation";
|
||||
private mBorderSize: number = 5;
|
||||
|
@ -35,7 +37,7 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
private mRadius: number = 0;
|
||||
private mRColor: number = 0;
|
||||
private mGColor: number = 0;
|
||||
private mBColor: number= 0;
|
||||
private mBColor: number = 0;
|
||||
|
||||
constructor(border_size: number, value: rgbColor) {
|
||||
this.mRColor = value.g_color;
|
||||
|
@ -44,14 +46,26 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
this.mBorderSize = border_size;
|
||||
}
|
||||
|
||||
getClassName() {
|
||||
return "CropCircleWithBorderTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams() {
|
||||
return JSON.stringify([this.mBorderSize, {
|
||||
r_color: this.mRColor,
|
||||
g_color: this.mGColor,
|
||||
b_color: this.mBColor
|
||||
}]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return CropCircleWithBorderTransformation.TAG + ";mBorderSize:" + this.mBorderSize
|
||||
+ ";mCenterX:" + this.mCenterX
|
||||
+ ";mCenterY:" + this.mCenterY
|
||||
+ ";mRadius:" + this.mRadius
|
||||
+ ";mRColor:" + this.mRColor
|
||||
+ ";mGColor:" + this.mGColor
|
||||
+ ";mBColor:" + this.mBColor;
|
||||
+ ";mCenterX:" + this.mCenterX
|
||||
+ ";mCenterY:" + this.mCenterY
|
||||
+ ";mRadius:" + this.mRadius
|
||||
+ ";mRColor:" + this.mRColor
|
||||
+ ";mGColor:" + this.mGColor
|
||||
+ ";mBColor:" + this.mBColor;
|
||||
}
|
||||
|
||||
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
|
@ -62,28 +76,30 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
}
|
||||
return;
|
||||
}
|
||||
let imageSource:image.ImageSource = image.createImageSource(buf);
|
||||
TransformUtils.getPixelMapSize(imageSource, {asyncTransform:(error:BusinessError|string, size:Size|null) => {
|
||||
if (!size) {
|
||||
func?.asyncTransform(error, null)
|
||||
return;
|
||||
let imageSource: image.ImageSource = image.createImageSource(buf);
|
||||
TransformUtils.getPixelMapSize(imageSource, {
|
||||
asyncTransform: (error: BusinessError | string, size: Size | null) => {
|
||||
if (!size) {
|
||||
func?.asyncTransform(error, null)
|
||||
return;
|
||||
}
|
||||
let pixelMapWidth = size.width;
|
||||
let pixelMapHeight = size.height;
|
||||
let targetWidth = request.size.width;
|
||||
let targetHeight = request.size.height;
|
||||
if (pixelMapWidth < targetWidth) {
|
||||
targetWidth = pixelMapWidth;
|
||||
}
|
||||
if (pixelMapHeight < targetHeight) {
|
||||
targetHeight = pixelMapHeight;
|
||||
}
|
||||
this.updatePixelMapSize(imageSource, targetWidth, targetHeight, func);
|
||||
}
|
||||
let pixelMapWidth = size.width;
|
||||
let pixelMapHeight = size.height;
|
||||
let targetWidth = request.size.width;
|
||||
let targetHeight = request.size.height;
|
||||
if (pixelMapWidth < targetWidth) {
|
||||
targetWidth = pixelMapWidth;
|
||||
}
|
||||
if (pixelMapHeight < targetHeight) {
|
||||
targetHeight = pixelMapHeight;
|
||||
}
|
||||
this.updatePixelMapSize(imageSource, targetWidth, targetHeight, func);
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
private updatePixelMapSize(imageSource: image.ImageSource, outWith: number, outHeight: number, func?: AsyncTransform<PixelMap>) {
|
||||
let options:image.DecodingOptions = {
|
||||
let options: image.DecodingOptions = {
|
||||
editable: true,
|
||||
desiredSize: {
|
||||
width: outWith,
|
||||
|
@ -91,13 +107,13 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
}
|
||||
}
|
||||
imageSource.createPixelMap(options)
|
||||
.then((pixelMap:PixelMap) => {
|
||||
.then((pixelMap: PixelMap) => {
|
||||
this.transformPixelMap(pixelMap, outWith, outHeight, func);
|
||||
imageSource.release()
|
||||
})
|
||||
.catch((e:BusinessError) => {
|
||||
.catch((e: BusinessError) => {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation e:" + e);
|
||||
if (func!=undefined) {
|
||||
if (func != undefined) {
|
||||
func?.asyncTransform(Constants.PROJECT_TAG + ";CropCircleWithBorderTransformation e:" + e, null);
|
||||
}
|
||||
imageSource.release()
|
||||
|
@ -120,8 +136,8 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
|
||||
let dataArray = new Uint8Array(bufferData);
|
||||
|
||||
for (let h = 0;h <= height; h++) {
|
||||
for (let w = 0;w <= width; w++) {
|
||||
for (let h = 0; h <= height; h++) {
|
||||
for (let w = 0; w <= width; w++) {
|
||||
// 不在大圆之内的设置透明
|
||||
// 在大圆与小圆之间的 设置rgb值
|
||||
// 小圆之内的不变
|
||||
|
@ -154,16 +170,16 @@ export class CropCircleWithBorderTransformation implements BaseTransform<PixelMa
|
|||
}
|
||||
|
||||
isContainsCircle(x: number, y: number): boolean {
|
||||
let a:number = Math.pow((this.mCenterX - x), 2);
|
||||
let b:number = Math.pow((this.mCenterY - y), 2);
|
||||
let c:number = Math.sqrt((a + b));
|
||||
let a: number = Math.pow((this.mCenterX - x), 2);
|
||||
let b: number = Math.pow((this.mCenterY - y), 2);
|
||||
let c: number = Math.sqrt((a + b));
|
||||
return c <= this.mRadius;
|
||||
}
|
||||
|
||||
isContainsSmallCircle(x: number, y: number): boolean {
|
||||
let a:number = Math.pow((this.mCenterX - x), 2);
|
||||
let b:number = Math.pow((this.mCenterY - y), 2);
|
||||
let c:number = Math.sqrt((a + b));
|
||||
let a: number = Math.pow((this.mCenterX - x), 2);
|
||||
let b: number = Math.pow((this.mCenterY - y), 2);
|
||||
let c: number = Math.sqrt((a + b));
|
||||
return c <= (this.mRadius - this.mBorderSize);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,14 @@ import image from "@ohos.multimedia.image"
|
|||
export class CropSquareTransformation implements BaseTransform<PixelMap> {
|
||||
private static TAG: string = "CropSquareTransformation";
|
||||
|
||||
getClassName(){
|
||||
return "CropSquareTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
getName() {
|
||||
return CropSquareTransformation.TAG;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ export class CropTransformation implements BaseTransform<PixelMap> {
|
|||
this.mCropType = cropType;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "CropTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this.mWidth,this.mHeight ,this.mCropType]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return CropTransformation.TAG + ";mWidth:" + this.mWidth
|
||||
+ ";mHeight:" + this.mHeight
|
||||
|
|
|
@ -29,6 +29,14 @@ export class GrayscaleTransformation implements BaseTransform<PixelMap> {
|
|||
return "GrayscaleTransformation";
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "GrayscaleTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
if (!buf || buf.byteLength <= 0) {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";GrayscaleTransformation buf is empty");
|
||||
|
|
|
@ -36,6 +36,14 @@ export class InvertFilterTransformation implements BaseTransform<PixelMap> {
|
|||
return "InvertFilterTransformation";
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "InvertFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
if (!buf || buf.byteLength <= 0) {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";InvertFilterTransformation buf is empty");
|
||||
|
|
|
@ -32,6 +32,14 @@ export class KuwaharaFilterTransform implements BaseTransform<PixelMap> {
|
|||
this._mRadius = radius;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "KuwaharaFilterTransform";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this._mRadius]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "KuwaharaFilterTransform _mRadius:" + this._mRadius;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ export class MaskTransformation implements BaseTransform<PixelMap> {
|
|||
this._mResourceData = maskBitmap;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "MaskTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this._mResourceData]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "MaskTransformation:" + this._mResourceData;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,14 @@ export class PixelationFilterTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "PixelationFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this._mPixel]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "PixelationFilterTransformation" + this._mPixel;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,14 @@ export class RotateImageTransformation implements BaseTransform<PixelMap> {
|
|||
return "RotateImageTransformation" + ";degreesToRotate:" + this.mDegreesToRotate;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "RotateImageTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this.mDegreesToRotate]);
|
||||
}
|
||||
|
||||
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
if (!buf || buf.byteLength <= 0) {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";RotateImageTransformation buf is empty");
|
||||
|
|
|
@ -46,6 +46,19 @@ export class RoundedCornersTransformation implements BaseTransform<PixelMap> {
|
|||
this.mBottom_right = value.bottom_right;
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "RoundedCornersTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([{
|
||||
top_left: this.mTop_left,
|
||||
top_right: this.mTop_right,
|
||||
bottom_left: this.mBottom_left,
|
||||
bottom_right: this.mBottom_right
|
||||
}]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "RoundedCornersTransformation" + ";mTop_left:" + this.mTop_left
|
||||
+ ";mTop_right:" + this.mTop_right
|
||||
|
|
|
@ -33,6 +33,14 @@ export class SepiaFilterTransformation implements BaseTransform<PixelMap> {
|
|||
return "SepiaFilterTransformation";
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "SepiaFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
async transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
if (!buf || buf.byteLength <= 0) {
|
||||
LogUtil.log(Constants.PROJECT_TAG + ";SepiaFilterTransformation buf is empty");
|
||||
|
|
|
@ -24,6 +24,15 @@ import { BusinessError } from '@ohos.base'
|
|||
import {Size} from '../../imageknife/RequestOption'
|
||||
|
||||
export class SketchFilterTransformation implements BaseTransform<PixelMap> {
|
||||
|
||||
getClassName(){
|
||||
return "SketchFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
getName() {
|
||||
return 'SketchFilterTransformation';
|
||||
}
|
||||
|
|
|
@ -43,6 +43,14 @@ export class SwirlFilterTransformation implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "SwirlFilterTransformation";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this.radius,this._angle,[this._xCenter,this._yCenter]]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return 'SwirlFilterTransformation' + this.radius;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,14 @@ export class ToonFilterTransform implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "ToonFilterTransform";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this.threshold,this.quantizationLevels]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "ToonFilterTransform threshold:" + this.threshold + ";quantizationLevels:" + this.quantizationLevels;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,14 @@ export class VignetteFilterTransform implements BaseTransform<PixelMap> {
|
|||
}
|
||||
}
|
||||
|
||||
getClassName(){
|
||||
return "VignetteFilterTransform";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return JSON.stringify([this.centerPoint,this.vignetteColor,this.vignetteSpace]);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return "VignetteFilterTransform centerPoint:" + this.centerPoint + ";vignetteColor:" + this.vignetteColor + ";vignetteSpace:" + this.vignetteSpace;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,15 @@ import {TransformUtils} from '../TransformUtils'
|
|||
import {RequestOption} from '../../../imageknife/RequestOption'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
export class CenterCrop implements BaseTransform<PixelMap> {
|
||||
|
||||
getClassName(){
|
||||
return "CenterCrop";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
getName() {
|
||||
return 'CenterCrop:' + this;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,13 @@ export class CenterInside implements BaseTransform<PixelMap> {
|
|||
getName() {
|
||||
return 'CenterInside:' + this;
|
||||
}
|
||||
getClassName(){
|
||||
return "CenterInside";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
if (!buf || buf.byteLength <= 0) {
|
||||
|
|
|
@ -23,6 +23,13 @@ export class FitCenter implements BaseTransform<PixelMap> {
|
|||
getName() {
|
||||
return 'FitCenter:' + this;
|
||||
}
|
||||
getClassName(){
|
||||
return "FitCenter";
|
||||
}
|
||||
|
||||
getConstructorParams(){
|
||||
return '[]';
|
||||
}
|
||||
|
||||
transform(buf: ArrayBuffer, request: RequestOption, func?: AsyncTransform<PixelMap>) {
|
||||
if (!buf || buf.byteLength <= 0) {
|
||||
|
|
|
@ -24,69 +24,32 @@ export class ParseImageUtil implements IParseImage<PixelMap> {
|
|||
this.parseImageThumbnail(1, imageinfo, onCompleteFunction, onErrorFunction)
|
||||
}
|
||||
|
||||
// scale(0,1)
|
||||
parseImageThumbnail(scale: number, imageinfo: ArrayBuffer, onCompleteFunction: (value: PixelMap) => void | PromiseLike<PixelMap>, onErrorFunction: (reason?: BusinessError | string) => void) {
|
||||
|
||||
// let imageSource: image.ImageSource = image.createImageSource(imageinfo); // 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||
// imageSource.getImageInfo().then((value) => {
|
||||
// let hValue = Math.round(value.size.height * scale);
|
||||
// let wValue = Math.round(value.size.width * scale);
|
||||
// let defaultSize: image.Size = {
|
||||
// height: hValue,
|
||||
// width: wValue
|
||||
// };
|
||||
// let opts: image.DecodingOptions = {
|
||||
// editable: true,
|
||||
// desiredSize: defaultSize
|
||||
// };
|
||||
//
|
||||
// imageSource.createPixelMap(opts).then((pixelMap: image.PixelMap) => {
|
||||
// onCompleteFunction(pixelMap);
|
||||
// imageSource.release()
|
||||
// }).catch((err: string) => {
|
||||
// onErrorFunction(err);
|
||||
// imageSource.release()
|
||||
// })
|
||||
//
|
||||
// }).catch((err: string) => {
|
||||
// onErrorFunction(err);
|
||||
// imageSource.release()
|
||||
// })
|
||||
let imageSource: image.ImageSource = image.createImageSource(imageinfo); // 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||
imageSource.getImageInfo().then((value) => {
|
||||
let hValue = Math.round(value.size.height * scale);
|
||||
let wValue = Math.round(value.size.width * scale);
|
||||
let defaultSize: image.Size = {
|
||||
height: hValue,
|
||||
width: wValue
|
||||
};
|
||||
let opts: image.DecodingOptions = {
|
||||
editable: true,
|
||||
desiredSize: defaultSize
|
||||
};
|
||||
|
||||
taskPoolExecutePixelMap(imageinfo,scale,onCompleteFunction,onErrorFunction); //多线程接口
|
||||
imageSource.createPixelMap(opts).then((pixelMap: image.PixelMap) => {
|
||||
onCompleteFunction(pixelMap);
|
||||
imageSource.release()
|
||||
}).catch((err: string) => {
|
||||
onErrorFunction(err);
|
||||
imageSource.release()
|
||||
})
|
||||
|
||||
}).catch((err: string) => {
|
||||
onErrorFunction(err);
|
||||
imageSource.release()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Concurrent
|
||||
async function taskParseImage(arrayBuffer: ArrayBuffer, scale: number): Promise<PixelMap> {
|
||||
let imageSource: image.ImageSource = image.createImageSource(arrayBuffer); // 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||
let value = await imageSource.getImageInfo();
|
||||
let hValue = Math.round(value.size.height * scale);
|
||||
let wValue = Math.round(value.size.width * scale);
|
||||
let defaultSize: image.Size = {
|
||||
height: hValue,
|
||||
width: wValue
|
||||
};
|
||||
let opts: image.DecodingOptions = {
|
||||
editable: true,
|
||||
desiredSize: defaultSize
|
||||
};
|
||||
let pixelMap = await imageSource.createPixelMap(opts)
|
||||
LogUtil.log("ceshi321 : Succeeded in creating pixelmap taskpool " + pixelMap.getPixelBytesNumber())
|
||||
imageSource.release()
|
||||
return pixelMap;
|
||||
}
|
||||
|
||||
function taskPoolExecutePixelMap(arrayBuffer: ArrayBuffer, scale: number, onCompleteFunction: (value: PixelMap) => void | PromiseLike<PixelMap>, onErrorFunction: (reason?: BusinessError | string) => void) {
|
||||
LogUtil.log("ceshi321 : arrayBuffer长度" + arrayBuffer.byteLength)
|
||||
let task = new taskpool.Task(taskParseImage, arrayBuffer, scale)
|
||||
task.setTransferList([])
|
||||
taskpool.execute(task).then((pixelmap: Object) => {
|
||||
LogUtil.log('ceshi321 : Succeeded in creating pixelmap Ui .' + (pixelmap as image.PixelMap).getPixelBytesNumber())
|
||||
onCompleteFunction(pixelmap as image.PixelMap);
|
||||
}).catch((err: string) => {
|
||||
LogUtil.log("ceshi321 : test occur error: " + err)
|
||||
onErrorFunction(err);
|
||||
});
|
||||
}
|
|
@ -36,88 +36,44 @@ export interface gifBackData {
|
|||
export class GIFParseImpl implements IParseGif {
|
||||
parseGifs(imageinfo: ArrayBuffer, callback: (data?: GIFFrame[], err?: BusinessError | string) => void) {
|
||||
// 硬解码流程
|
||||
// let imageSource = image.createImageSource(imageinfo);
|
||||
// let decodeOpts: image.DecodingOptions = {
|
||||
// sampleSize: 1,
|
||||
// editable: true,
|
||||
// rotate: 0
|
||||
// }
|
||||
// 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.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]
|
||||
// }
|
||||
// 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)
|
||||
// })
|
||||
taskPoolExecutePixelMapList(imageinfo,callback); //多线程接口
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Concurrent
|
||||
async function taskParseGif(arrayBuffer: ArrayBuffer): Promise<GIFFrame[]> {
|
||||
let imageSource = image.createImageSource(arrayBuffer);
|
||||
let data: GIFFrame[] = [];
|
||||
let decodeOpts: image.DecodingOptions = {
|
||||
sampleSize: 1,
|
||||
editable: true,
|
||||
rotate: 0
|
||||
}
|
||||
let pixelList = await imageSource.createPixelMapList(decodeOpts);
|
||||
if (pixelList.length > 0) {
|
||||
let pixelmap = pixelList[0];
|
||||
let imageInfo = await pixelmap.getImageInfo();
|
||||
let delayTimes = await imageSource.getDelayTimeList();
|
||||
for (let i = 0; i < pixelList.length; i++) {
|
||||
let frame = new GIFFrame();
|
||||
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]
|
||||
}
|
||||
data.push(frame)
|
||||
let imageSource = image.createImageSource(imageinfo);
|
||||
let decodeOpts: image.DecodingOptions = {
|
||||
sampleSize: 1,
|
||||
editable: true,
|
||||
rotate: 0
|
||||
}
|
||||
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.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]
|
||||
}
|
||||
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)
|
||||
})
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function taskPoolExecutePixelMapList(arrayBuffer: ArrayBuffer, callback: (data?: GIFFrame[], err?: BusinessError | string) => void) {
|
||||
LogUtil.log("ceshi321 : arrayBuffer长度" + arrayBuffer.byteLength)
|
||||
let task = new taskpool.Task(taskParseGif, arrayBuffer)
|
||||
task.setTransferList([])
|
||||
taskpool.execute(task).then((imageFrames: Object) => {
|
||||
// LogUtil.log('ceshi321 : Succeeded in creating pixelmap Ui .' + imageFrames.getPixelBytesNumber())
|
||||
callback(imageFrames as GIFFrame[],undefined)
|
||||
}).catch((err: string) => {
|
||||
LogUtil.log("ceshi321 : test occur error: " + err)
|
||||
callback(undefined,err);
|
||||
});
|
||||
}
|
|
@ -19,6 +19,6 @@ import { ImageKnifeData } from '../../ImageKnifeData'
|
|||
export interface IParseSvg {
|
||||
// 解析svg
|
||||
parseSvg:(option: RequestOption, imageInfo: ArrayBuffer | ArrayBufferLike,
|
||||
onComplete: (value: ImageKnifeData) => void | PromiseLike<ImageKnifeData>,
|
||||
onComplete: (value: PixelMap) => void | PromiseLike<ImageKnifeData>,
|
||||
onErrorFunction: (reason?: BusinessError | string) => void)=> void
|
||||
}
|
|
@ -20,7 +20,7 @@ import image from '@ohos.multimedia.image'
|
|||
|
||||
export class SVGParseImpl implements IParseSvg {
|
||||
parseSvg(option: RequestOption, imageInfo: ArrayBuffer,
|
||||
onComplete: (value: ImageKnifeData) => void | PromiseLike<ImageKnifeData>,
|
||||
onComplete: (value: PixelMap) => void | PromiseLike<ImageKnifeData>,
|
||||
onErrorFunction: (reason?: BusinessError | string) => void) {
|
||||
|
||||
let imageSource: image.ImageSource = image.createImageSource(imageInfo); // 步骤一:文件转为pixelMap 然后变换 给Image组件
|
||||
|
@ -36,7 +36,7 @@ export class SVGParseImpl implements IParseSvg {
|
|||
};
|
||||
imageSource.createPixelMap(opts).then((pixelMap: image.PixelMap) => {
|
||||
let imageKnifeData = ImageKnifeData.createImagePixelMap(ImageKnifeType.PIXELMAP, pixelMap)
|
||||
onComplete(imageKnifeData);
|
||||
onComplete(imageKnifeData?.drawPixelMap?.imagePixelMap as PixelMap);
|
||||
imageSource.release()
|
||||
}).catch((err: string) => {
|
||||
onErrorFunction(err);
|
||||
|
|
Loading…
Reference in New Issue