更新说明
1、.jpg .png .gif解码功能使用taskpool实现 2、 修复了内存缓存张数设置为1时gif图片消失的问题 Signed-off-by: 明月清风 <qiufeihu1@h-partners.com>
This commit is contained in:
parent
db7f176084
commit
2006641248
|
@ -1,3 +1,9 @@
|
|||
## 2.1.1-rc.5
|
||||
- .jpg .png .gif解码功能使用taskpool实现
|
||||
- 修复了内存缓存张数设置为1时gif图片消失的问题
|
||||
|
||||
|
||||
|
||||
## 2.1.1-rc.4
|
||||
|
||||
- 删除pako源码依赖,使用ohpm依赖
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import router from '@system.router';
|
||||
import router from '@ohos.router';
|
||||
import {
|
||||
ImageKnifeComponent,
|
||||
ImageKnifeOption,
|
||||
|
@ -67,7 +67,6 @@ struct IndexFunctionDemo {
|
|||
.onClick(() => {
|
||||
this.imageKnifeOption2 = {
|
||||
loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
|
||||
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
displayProgress:true,
|
||||
|
@ -80,7 +79,7 @@ struct IndexFunctionDemo {
|
|||
Button("ImageKnife测试目录页面")
|
||||
.onClick(() => {
|
||||
console.log("pages/imageknifeTestCaseIndex 页面跳转")
|
||||
router.push({ uri: "pages/imageknifeTestCaseIndex" });
|
||||
router.replaceUrl({ url: "pages/imageknifeTestCaseIndex" });
|
||||
}).margin({ top: 15 })
|
||||
}.width('100%').height(60).backgroundColor(Color.Pink)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
import hilog from '@ohos.hilog';
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
|
||||
import {ImageKnife,ImageKnifeDrawFactory,ImageKnifeGlobal} from '@ohos/libraryimageknife'
|
||||
import {ImageKnife,ImageKnifeDrawFactory,ImageKnifeGlobal} from '@ohos/imageknife'
|
||||
|
||||
export default function ImageKnifeTest() {
|
||||
describe('ImageKnifeTest', ()=> {
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
"main": "index.ets",
|
||||
"repository": "https://gitee.com/openharmony-tpc/ImageKnife",
|
||||
"type": "module",
|
||||
"version": "2.1.1-rc.4",
|
||||
"version": "2.1.1-rc.5",
|
||||
"dependencies": {
|
||||
"pako": "^2.1.0",
|
||||
"@ohos/disklrucache": "^2.0.2-rc.0",
|
||||
"@ohos/svg": "^2.1.1-rc.0",
|
||||
"@ohos/gpu_transform": "^1.0.0",
|
||||
"pako": "^2.1.0"
|
||||
"@ohos/gpu_transform": "^1.0.0"
|
||||
},
|
||||
"tags": [
|
||||
"ImageCache",
|
||||
|
|
|
@ -330,12 +330,6 @@ export class ImageKnife {
|
|||
|
||||
let signature = request.signature;
|
||||
|
||||
if (signature != undefined) {
|
||||
console.log("唯一标识:" + signature.getKey())
|
||||
}
|
||||
|
||||
|
||||
|
||||
cacheKey = factories.generateMemoryCacheKey(loadKey,size,transformed,dontAnimateFlag,signature);
|
||||
|
||||
// 生成磁盘缓存变换后数据key 变换后数据保存在磁盘
|
||||
|
|
|
@ -85,6 +85,9 @@ export struct ImageKnifeComponent {
|
|||
|
||||
private detachFromLayout:DetachFromLayout|undefined = undefined;
|
||||
|
||||
private detachFromLayoutGIF :DetachFromLayout|undefined = undefined;
|
||||
|
||||
|
||||
build() {
|
||||
Canvas(this.context)
|
||||
.width('100%')
|
||||
|
@ -519,7 +522,11 @@ export struct ImageKnifeComponent {
|
|||
LogUtil.log('ImageKnifeComponent default drawMainSource end!')
|
||||
})
|
||||
} else if (data.isGIFFrame()) {
|
||||
this.drawGIFFrame(context, data, imageKnifeOption, compWidth, compHeight, setGifTimeId)
|
||||
if(data.drawGIFFrame != undefined) {
|
||||
data.drawGIFFrame.isShowOnComponent = true
|
||||
this.detachFromLayoutGIF = data.drawGIFFrame.detachFromLayoutGIF
|
||||
this.drawGIFFrame(context, data, imageKnifeOption, compWidth, compHeight, setGifTimeId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,7 +611,9 @@ export struct ImageKnifeComponent {
|
|||
if(this.detachFromLayout != undefined){
|
||||
this.detachFromLayout.detach();
|
||||
}
|
||||
|
||||
if(this.detachFromLayoutGIF != undefined){
|
||||
this.detachFromLayoutGIF.detach();
|
||||
}
|
||||
this.resetGifData();
|
||||
}
|
||||
|
||||
|
@ -750,23 +759,7 @@ export struct ImageKnifeComponent {
|
|||
LogUtil.log('ImageKnifeComponent canvasDrawPixelMap index=' + index)
|
||||
let frame = frames[index];
|
||||
let pixelmap = frame['drawPixelMap']
|
||||
let disposal = 0
|
||||
// disposal value is from preFrame
|
||||
if (index >= 1) {
|
||||
let preFrame = frames[index-1]
|
||||
disposal = preFrame.disposalType
|
||||
|
||||
if (disposal === FrameDisposalType.DISPOSE_RestoreBackground) {
|
||||
let left:number = preFrame.dims.left;
|
||||
let top:number = preFrame.dims.top
|
||||
context.clearRect(left, top, compWidth, compHeight);
|
||||
}
|
||||
} else {
|
||||
if (disposal === FrameDisposalType.DISPOSE_RestoreBackground) {
|
||||
context.clearRect(0, 0, compWidth, compHeight)
|
||||
}
|
||||
}
|
||||
|
||||
context.clearRect(0, 0, compWidth, compHeight)
|
||||
let scaleType = (typeof this.imageKnifeOption.mainScaleType == 'number') ? this.imageKnifeOption.mainScaleType : ScaleType.FIT_CENTER
|
||||
context.save();
|
||||
let frameW = frames[0].dims.left + frames[0].dims.width
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
import { GIFFrame } from './utils/gif/GIFFrame'
|
||||
import { DetachFromLayout } from './RequestOption'
|
||||
|
||||
export enum ImageKnifeType {
|
||||
PIXELMAP = 'PixelMap',
|
||||
|
@ -35,6 +36,26 @@ export class DrawResource {
|
|||
|
||||
export class DrawGIFFrame {
|
||||
imageGIFFrames: GIFFrame[] | undefined = undefined
|
||||
isShowOnComponent:boolean = false;//gif是否显示在组件上 true:显示在组件上 false:不显示在组件上
|
||||
isLruCacheRelease:boolean = false;//当前lru是否释放gif资源,true的就释放了gif资源 false就是没有释放
|
||||
|
||||
detachFromLayoutGIF :DetachFromLayout = {
|
||||
detach:()=> {
|
||||
this.isShowOnComponent = false
|
||||
if(this.isLruCacheRelease) {
|
||||
let gifFrames = this.imageGIFFrames;
|
||||
if (gifFrames != undefined) {
|
||||
for (let i = 0; i < gifFrames.length; i++) {
|
||||
let tempFrame = gifFrames[i];
|
||||
if (tempFrame.drawPixelMap != undefined) {
|
||||
tempFrame.drawPixelMap.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
this.imageGIFFrames = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class ImageKnifeData {
|
||||
|
@ -97,14 +118,21 @@ export class ImageKnifeData {
|
|||
}
|
||||
}
|
||||
if(this.isGIFFrame()){
|
||||
if(this.drawGIFFrame != undefined){
|
||||
let gifFrames = this.drawGIFFrame.imageGIFFrames;
|
||||
if(gifFrames != undefined){
|
||||
for (let i = 0; i < gifFrames.length; i++) {
|
||||
let tempFrame = gifFrames[i];
|
||||
if(tempFrame.drawPixelMap != undefined){
|
||||
tempFrame.drawPixelMap.release()
|
||||
if (this.drawGIFFrame != undefined) {
|
||||
this.drawGIFFrame.isLruCacheRelease = true;
|
||||
|
||||
if(this.drawGIFFrame.isShowOnComponent){
|
||||
return;
|
||||
}else {
|
||||
let gifFrames = this.drawGIFFrame.imageGIFFrames;
|
||||
if (gifFrames != undefined) {
|
||||
for (let i = 0; i < gifFrames.length; i++) {
|
||||
let tempFrame = gifFrames[i];
|
||||
if (tempFrame.drawPixelMap != undefined) {
|
||||
tempFrame.drawPixelMap.release()
|
||||
}
|
||||
}
|
||||
this.drawGIFFrame.imageGIFFrames = undefined
|
||||
}
|
||||
this.drawGIFFrame.imageGIFFrames = undefined
|
||||
}
|
||||
|
|
|
@ -13,44 +13,54 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {IParseImage} from '../interface/IParseImage'
|
||||
import { IParseImage } from '../interface/IParseImage'
|
||||
import image from '@ohos.multimedia.image';
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import taskpool from '@ohos.taskpool';
|
||||
import { LogUtil } from './LogUtil';
|
||||
|
||||
export class ParseImageUtil implements IParseImage<PixelMap> {
|
||||
parseImage(imageinfo: ArrayBuffer, onCompleteFunction:(value:PixelMap)=>void | PromiseLike<PixelMap>, onErrorFunction:(reason?:BusinessError|string)=>void) {
|
||||
parseImage(imageinfo: ArrayBuffer, onCompleteFunction: (value: PixelMap) => void | PromiseLike<PixelMap>, onErrorFunction: (reason?: BusinessError | string) => void) {
|
||||
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((err, value) => {
|
||||
if (err) {
|
||||
onErrorFunction(err);
|
||||
return;
|
||||
}
|
||||
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, (err, pixelmap) => {
|
||||
if (err) {
|
||||
onErrorFunction(err);
|
||||
} else {
|
||||
onCompleteFunction(pixelmap);
|
||||
}
|
||||
imageSource.release()
|
||||
})
|
||||
|
||||
})
|
||||
parseImageThumbnail(scale: number, imageinfo: ArrayBuffer, onCompleteFunction: (value: PixelMap) => void | PromiseLike<PixelMap>, onErrorFunction: (reason?: BusinessError | string) => void) {
|
||||
taskPoolExecutePixelMap(imageinfo,scale,onCompleteFunction,onErrorFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// let TAG:string = "ParseImageUtil_TASK"
|
||||
|
||||
@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)
|
||||
taskpool.execute(task).then((pixelmap: image.PixelMap) => {
|
||||
LogUtil.log('ceshi321 : Succeeded in creating pixelmap Ui .' + pixelmap.getPixelBytesNumber())
|
||||
onCompleteFunction(pixelmap);
|
||||
}).catch((err: string) => {
|
||||
LogUtil.log("ceshi321 : test occur error: " + err)
|
||||
onErrorFunction(err);
|
||||
});
|
||||
}
|
|
@ -12,68 +12,70 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { IParseGif } from './IParseGif'
|
||||
import { IParseGif } from './IParseGif'
|
||||
import { Dims, GIFFrame } from './GIFFrame'
|
||||
import image from '@ohos.multimedia.image'
|
||||
import { BusinessError } from '@ohos.base'
|
||||
import worker, { ErrorEvent, MessageEvents } from '@ohos.worker';
|
||||
import taskpool from '@ohos.taskpool'
|
||||
import { LogUtil } from '../LogUtil'
|
||||
|
||||
export interface senderData{
|
||||
type:string,
|
||||
data:ArrayBuffer;
|
||||
export interface senderData {
|
||||
type: string,
|
||||
data: ArrayBuffer;
|
||||
}
|
||||
|
||||
export interface gifBackData{
|
||||
dims:Dims[],
|
||||
delay:number[],
|
||||
disposalType:number[],
|
||||
patch:Uint8ClampedArray[],
|
||||
transparentIndex:number[]
|
||||
export interface gifBackData {
|
||||
dims: Dims[],
|
||||
delay: number[],
|
||||
disposalType: number[],
|
||||
patch: Uint8ClampedArray[],
|
||||
transparentIndex: number[]
|
||||
}
|
||||
|
||||
export class GIFParseImpl implements IParseGif {
|
||||
//
|
||||
parseGifs(imageinfo: ArrayBuffer, callback: (data?:GIFFrame[], err?:BusinessError|string) => void, worker?:worker.ThreadWorker,runMainThread?:boolean) {
|
||||
// 硬解码流程
|
||||
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)
|
||||
})
|
||||
|
||||
parseGifs(imageinfo: ArrayBuffer, callback: (data?: GIFFrame[], err?: BusinessError | string) => void) {
|
||||
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 pixelmap1 = pixelList[0];
|
||||
let imageInfo = await pixelmap1.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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
taskpool.execute(task).then((imageFrames: GIFFrame[]) => {
|
||||
// LogUtil.log('ceshi321 : Succeeded in creating pixelmap Ui .' + imageFrames.getPixelBytesNumber())
|
||||
callback(imageFrames,undefined)
|
||||
}).catch((err: string) => {
|
||||
LogUtil.log("ceshi321 : test occur error: " + err)
|
||||
callback(undefined,err);
|
||||
});
|
||||
}
|
|
@ -6,6 +6,6 @@
|
|||
"name": "imageknife",
|
||||
"description": "example description",
|
||||
"repository": {},
|
||||
"version": "2.1.1-rc.4",
|
||||
"version": "2.1.1-rc.5",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue