|
|
|
@ -14,11 +14,7 @@
|
|
|
|
|
*/
|
|
|
|
|
import { IParseGif } from './IParseGif'
|
|
|
|
|
import { Dims, GIFFrame } from './GIFFrame'
|
|
|
|
|
import { LoadType } from '../../../../../../../GifWorker'
|
|
|
|
|
import { parseBufferToFrame } from './parse/GIFParse'
|
|
|
|
|
import { LogUtil } from '../../utils/LogUtil'
|
|
|
|
|
import image from '@ohos.multimedia.image'
|
|
|
|
|
import { ImageKnifeGlobal } from '../../ImageKnifeGlobal'
|
|
|
|
|
import { BusinessError } from '@ohos.base'
|
|
|
|
|
import worker, { ErrorEvent, MessageEvents } from '@ohos.worker';
|
|
|
|
|
|
|
|
|
@ -35,143 +31,49 @@ export interface gifBackData{
|
|
|
|
|
transparentIndex:number[]
|
|
|
|
|
}
|
|
|
|
|
export class GIFParseImpl implements IParseGif {
|
|
|
|
|
//
|
|
|
|
|
parseGifs(imageinfo: ArrayBuffer, callback: (data?:GIFFrame[], err?:BusinessError|string) => void, worker?:worker.ThreadWorker,runMainThread?:boolean) {
|
|
|
|
|
let resolveWorker = worker;
|
|
|
|
|
LogUtil.log('parseGifs resolveWorker1 is null =' + (resolveWorker == null))
|
|
|
|
|
if (!resolveWorker && ImageKnifeGlobal.getInstance().getImageKnife() != undefined) {
|
|
|
|
|
resolveWorker = ImageKnifeGlobal.getInstance().getImageKnife()?.getGifWorker();
|
|
|
|
|
// 硬解码流程
|
|
|
|
|
let imageSource = image.createImageSource(imageinfo);
|
|
|
|
|
let decodeOpts: image.DecodingOptions = {
|
|
|
|
|
sampleSize: 1,
|
|
|
|
|
editable: true,
|
|
|
|
|
rotate: 0
|
|
|
|
|
}
|
|
|
|
|
LogUtil.log('parseGifs resolveWorker2 is null =' + (resolveWorker == null))
|
|
|
|
|
|
|
|
|
|
if (!!resolveWorker && !runMainThread) {
|
|
|
|
|
LogUtil.log('parseGifs in worker thread!')
|
|
|
|
|
let copyBuffer = imageinfo.slice(0);
|
|
|
|
|
this.useWorkerParse(resolveWorker, copyBuffer, (data, err) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
callback(undefined, err)
|
|
|
|
|
} else {
|
|
|
|
|
if (data != undefined) {
|
|
|
|
|
this.createPixelMapAll(data).then((pixelmaps) => {
|
|
|
|
|
if (pixelmaps.length == data.length) {
|
|
|
|
|
for (let i = 0;i < data.length; i++) {
|
|
|
|
|
let frame = data[i];
|
|
|
|
|
frame['drawPixelMap'] = pixelmaps[i];
|
|
|
|
|
frame['patch'] = undefined;
|
|
|
|
|
}
|
|
|
|
|
callback(data, undefined)
|
|
|
|
|
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]
|
|
|
|
|
}
|
|
|
|
|
}).catch((err: BusinessError) => {
|
|
|
|
|
callback(undefined, err)
|
|
|
|
|
})
|
|
|
|
|
}else{
|
|
|
|
|
callback(undefined, 'GIF Parse Error callback data is undefined')
|
|
|
|
|
}
|
|
|
|
|
data.push(frame)
|
|
|
|
|
}
|
|
|
|
|
callback(data,undefined)
|
|
|
|
|
imageSource.release();
|
|
|
|
|
}).catch((err: string) => {
|
|
|
|
|
imageSource.release();
|
|
|
|
|
callback(undefined,err)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}).catch((err: string) => {
|
|
|
|
|
imageSource.release();
|
|
|
|
|
callback(undefined,err)
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
LogUtil.log('parseGifs in main thread!')
|
|
|
|
|
let frames = parseBufferToFrame(imageinfo)
|
|
|
|
|
LogUtil.log('frames length =' + frames.length)
|
|
|
|
|
this.createPixelMapAll(frames).then((pixelmaps) => {
|
|
|
|
|
if (pixelmaps.length == frames.length) {
|
|
|
|
|
for (let i = 0;i < frames.length; i++) {
|
|
|
|
|
let frame = frames[i];
|
|
|
|
|
frame['drawPixelMap'] = pixelmaps[i];
|
|
|
|
|
frame['patch'] = undefined;
|
|
|
|
|
}
|
|
|
|
|
LogUtil.log('parseGifs in main thread! callback is done!')
|
|
|
|
|
callback(frames, undefined)
|
|
|
|
|
}
|
|
|
|
|
}).catch((err:BusinessError) => {
|
|
|
|
|
LogUtil.log('parseGifs in main thread! err =' + err)
|
|
|
|
|
callback(undefined, err)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createPixelMapAll(frames:GIFFrame[]): Promise<PixelMap[]> {
|
|
|
|
|
let promises:Promise<PixelMap>[] = new Array();
|
|
|
|
|
let filterCriteria = (item:GIFFrame) => {
|
|
|
|
|
if (!item['drawPixelMap']) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
frames.filter(filterCriteria, frames).flatMap<void,undefined>((frame:GIFFrame) => {
|
|
|
|
|
if(frame.patch != undefined) {
|
|
|
|
|
promises.push(image.createPixelMap(frame.patch.buffer, {
|
|
|
|
|
'size': {
|
|
|
|
|
'height': frame.dims.height as number,
|
|
|
|
|
'width': frame.dims.width as number
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}).catch((err: string) => {
|
|
|
|
|
imageSource.release();
|
|
|
|
|
callback(undefined,err)
|
|
|
|
|
})
|
|
|
|
|
return Promise.all<PixelMap>(promises)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private useWorkerParse(worker:worker.ThreadWorker, buffer: ArrayBuffer, callback: (data?:GIFFrame[], err?:BusinessError|string) => void) {
|
|
|
|
|
|
|
|
|
|
worker.onerror = (err:ErrorEvent)=>{
|
|
|
|
|
callback(undefined, err.message)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
worker.onmessageerror = (event: MessageEvents) => {
|
|
|
|
|
callback(undefined, event.type)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
worker.onexit = ()=> {
|
|
|
|
|
LogUtil.log('gifWork worker.onexit!')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
worker.onmessage = (e: MessageEvents) => {
|
|
|
|
|
let data:Record<string,Object> = e.data;
|
|
|
|
|
switch (data.type as string) {
|
|
|
|
|
case LoadType.loadBufferByWorker:
|
|
|
|
|
let pages:gifBackData = (data.data as gifBackData);
|
|
|
|
|
if (this.gifDecodeCorrect(pages)) {
|
|
|
|
|
let images = this.recDecodedData(pages);
|
|
|
|
|
callback(images, undefined)
|
|
|
|
|
} else {
|
|
|
|
|
callback(undefined, 'GIF Worker Decoder Data Is Error!')
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let obj:senderData = { type: LoadType.loadBufferByWorker, data: buffer }
|
|
|
|
|
worker.postMessage(obj, [buffer])
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private gifDecodeCorrect(frames:gifBackData) {
|
|
|
|
|
if (
|
|
|
|
|
(frames.patch.length == frames.dims.length) &&
|
|
|
|
|
(frames.patch.length == frames.delay.length) &&
|
|
|
|
|
(frames.patch.length == frames.disposalType.length) &&
|
|
|
|
|
(frames.patch.length == frames.patch.length) &&
|
|
|
|
|
(frames.patch.length == frames.transparentIndex.length)
|
|
|
|
|
) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 子线程数据回传处理
|
|
|
|
|
private recDecodedData(pages:gifBackData): GIFFrame[] {
|
|
|
|
|
let images:GIFFrame[] = new Array()
|
|
|
|
|
for (let i = 0; i < pages.patch.length; i++) {
|
|
|
|
|
let frame = new GIFFrame();
|
|
|
|
|
frame['dims'] = pages.dims[i]
|
|
|
|
|
frame['delay'] = pages.delay[i]
|
|
|
|
|
frame['disposalType'] = pages.disposalType[i]
|
|
|
|
|
let uint8ClampedArray = new Uint8ClampedArray(pages.patch[i])
|
|
|
|
|
frame['patch'] = uint8ClampedArray
|
|
|
|
|
frame['transparentIndex'] = pages.transparentIndex[i]
|
|
|
|
|
images.push(frame)
|
|
|
|
|
}
|
|
|
|
|
return images;
|
|
|
|
|
}
|
|
|
|
|
}
|