我有一个Unity应用,当我使用LoadImage加载大图像时,引擎会保持冻结主线程。
所以我决定尝试在与主线程不同的线程上对图像进行解码。我在这里使用C#jpeg解码器
https://gist.github.com/jandk/3889823
我写了一个测试代码来测试它。测试代码在主线程上旋转一个多维数据集。当多维数据集旋转时,我创建了一个单独的线程,其中从网站下载JPG图像并对其进行解码。解码后,主线程将使用这些解码后的位,并使用LoadRawImageData将它们应用于多维数据集
使用旋转多维数据集的想法是,由于多维数据集会暂时停止旋转,因此很容易看到由图像处理引起的任何引擎冻结。
这是代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System.Net;
using UnityEngine.UI;
using System.IO;
using Unity.Collections;
using UnityEngine.Networking;
using Jpeg;
public class Spin : MonoBehaviour
{
class ThreadedImageLoader : MonoBehaviour
{
public Thread thread = null;
public byte[] pixels = null;
public string url;
public bool done = false;
public GameObject g;
public void Download(string url,GameObject g)
{
this.url = url;
this.g = g;
Debug.Log("Downloading from url=" + url);
thread = new Thread(() => DoThread());
thread.Start();
}
public void DoThread()
{
Debug.Log("downloading pic on a thread");
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create(url);
string lsResponse = string.Empty;
using (HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse()) {
using (BinaryReader reader = new BinaryReader(lxResponse.GetResponseStream())) {
pixels = reader.ReadBytes(1 * 1024 * 1024 * 10);
}
}
Debug.Log("Done downloading, creating decoder...");
JpegDecoder jdec = new JpegDecoder(pixels);
Debug.Log("decoder created, decompressing...");
byte[] img = jdec.DecodeScan();
Debug.Log("Done decompressing");
done = true;
}
}
List<ThreadedImageLoader> loaders = new List<ThreadedImageLoader>();
public float delta = 1f;
void Start()
{
string url = "https://www.gstatic.com/webp/gallery/4.jpg";
ThreadedImageLoader td = gameObject.AddComponent<ThreadedImageLoader>();
loaders.Add(td);
td.Download(url,gameObject);
}
void Update()
{
float d = delta * Time.deltaTime;
transform.Rotate(new Vector3(d, d, d));
if (loaders.Count > 0) {
ThreadedImageLoader td = (ThreadedImageLoader)loaders[0];
if (td.done) {
Debug.Log("Update:pixels lenth:" + td.pixels.Length);
if (td.pixels.Length > 0) {
Texture2D t = new Texture2D(1, 1);
t.LoadRawTextureData(td.pixels);
t.Apply();
gameObject.GetComponent<Renderer>().material.mainTexture = t;
}
loaders.RemoveAt(0);
Destroy(td);
// keep downloading the image again
string url = "https://www.gstatic.com/webp/gallery/4.jpg";
ThreadedImageLoader tdd = gameObject.AddComponent<ThreadedImageLoader>();
loaders.Add(tdd);
tdd.Download(url,gameObject);
}
}
}
}
随着代码运行,多维数据集开始旋转,创建线程,从链接下载图像,但是在创建jpeg解码器时,它崩溃并在解码器内部出现读取图像错误。
即时通讯使用的jpeg解码器位于上面的链接中。看起来很简单,只有一个文件,但是在读取下载的数据时会停止解码并出错。
我知道下载的图像数据是正确的,因为如果对相同的数据使用LoadImage(pixels),则图像将完美显示。当然,我不能在实际代码中使用Loadimage,因为它会冻结主线程,因为它会解码主线程上的图像(这会导致冻结)。
有人知道在这种情况下可以使用的更好的c#jpeg解码器吗?一个可以在线程中运行并且没有太多依赖关系导致膨胀的问题? 我只需要它能够在Unity中的线程内解码jpeg。
我尝试了几个nuget软件包,但是无法让它们在Unity中正确安装。该链接上的那个是我发现的唯一一个易于使用的文件解码器,但是它当然崩溃了!
感谢您的帮助。