浏览代码

Fix gif memory problem.

/main
Yuncong Zhang 5 年前
当前提交
97bb9e76
共有 2 个文件被更改,包括 47 次插入69 次删除
  1. 9
      Runtime/ui/painting/GifDecoder.cs
  2. 107
      Runtime/ui/painting/codec_gif.cs

9
Runtime/ui/painting/GifDecoder.cs


this._gct = this._readColorTable(this._gctSize);
this._bgColor = this._gct[this._bgIndex];
}
this._currentFrame = new GifFrame {
bytes = new byte[this._width * this._height * sizeof(int)],
delay = 0
};
}
/**

this._setPixels(); // transfer pixel data to image
var bytes = new byte[this._width * this._height * sizeof(int)];
Buffer.BlockCopy(this._image, 0, bytes, 0, bytes.Length);
this._currentFrame = new GifFrame {bytes = bytes, delay = this._delay};
Buffer.BlockCopy(this._image, 0, this._currentFrame.bytes, 0, this._currentFrame.bytes.Length);
this._currentFrame.delay = this._delay;
this._frameCount++;
if (this._transparency) {

107
Runtime/ui/painting/codec_gif.cs


using System;
using System.Collections;
using System.Collections.Generic;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using UnityEngine;

public GifDecoder.GifFrame gifFrame;
}
readonly List<Promise<FrameData>> _frames;
volatile byte[] _bytes;
volatile int _width;
volatile int _height;
volatile int _frameCount;

volatile Texture2D _texture;
readonly UIWidgetsCoroutine _coroutine;
volatile FrameData _frameData;
volatile Image _image;
IEnumerator _coroutine;
this._frames = new List<Promise<FrameData>>();
this._width = 0;
this._height = 0;
this._bytes = bytes;
this._coroutine = this._startDecoding();
this._init();
this._texture = new Texture2D(this._width, this._height, TextureFormat.BGRA32, false);
this._texture.hideFlags = HideFlags.HideAndDontSave;
this._image = new Image(this._texture);
}
void _init() {
var bytesStream = new MemoryStream(this._bytes);
this._coroutine = Window.instance.startBackgroundCoroutine(
this._startDecoding(bytes, Window.instance));
var gifDecoder = new GifDecoder();
if (gifDecoder.read(bytesStream) != GifDecoder.STATUS_OK) {
throw new Exception("Failed to decode gif.");
}
this._width = gifDecoder.frameWidth;
this._height = gifDecoder.frameHeight;
IEnumerator _startDecoding(byte[] bytes, Window window) {
var bytesStream = new MemoryStream(bytes);
IEnumerator _startDecoding() {
var bytesStream = new MemoryStream(this._bytes);
var gifDecoder = new GifDecoder();
if (gifDecoder.read(bytesStream) != GifDecoder.STATUS_OK) {

int i = 0;
while (true) {
yield return null;
if (gifDecoder.nextFrame() != GifDecoder.STATUS_OK) {
throw new Exception("Failed to decode gif.");
}

}
var frameData = new FrameData {
gifFrame = gifDecoder.currentFrame,
gifFrame = gifDecoder.currentFrame
Promise<FrameData> frame;
this._frameData = frameData;
lock (this._frames) {
if (i < this._frames.Count) {
}
else {
D.assert(this._frames.Count == i);
this._frames.Add(new Promise<FrameData>());
}
i++;
frame = this._frames[i];
}
window.runInMain(() => { frame.Resolve(frameData); });
i++;
yield return null;
}
D.assert(gifDecoder.frameCount == i);

void _nextFrame() {
this._frameIndex++;
this._coroutine.MoveNext();
this._isDone = false;
this._coroutine = this._startDecoding();
this._coroutine.MoveNext();
Promise<FrameData> frame;
lock (this._frames) {
if (this._frameIndex == this._frames.Count) {
this._frames.Add(new Promise<FrameData>());
}
else {
D.assert(this._frameIndex < this._frames.Count);
}
frame = this._frames[this._frameIndex];
}
return frame.Then(frameData => {
this._nextFrame();
if (this._texture == null) {
this._texture = new Texture2D(this._width, this._height, TextureFormat.BGRA32, false);
this._texture.hideFlags = HideFlags.HideAndDontSave;
}
var tex = this._texture;
tex.LoadRawTextureData(frameData.gifFrame.bytes);
tex.Apply();
if (frameData.frameInfo != null) {
return frameData.frameInfo;
}
frameData.frameInfo = new FrameInfo {
image = new Image(tex),
duration = TimeSpan.FromMilliseconds(frameData.gifFrame.delay)
};
// frameData.gifFrame = null; // dispose gifFrame
return frameData.frameInfo;
});
this._nextFrame();
this._texture.LoadRawTextureData(this._frameData.gifFrame.bytes);
this._texture.Apply();
this._frameData.frameInfo = new FrameInfo() {
image = this._image,
duration = TimeSpan.FromMilliseconds(this._frameData.gifFrame.delay)
};
return Promise<FrameInfo>.Resolved(this._frameData.frameInfo);
this._coroutine.stop();
}
}
}
正在加载...
取消
保存