在Unity中的C#线程中解码Jpeg图像

时间:2019-03-01 21:36:34

标签: c# unity3d

我有一个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中正确安装。该链接上的那个是我发现的唯一一个易于使用的文件解码器,但是它当然崩溃了!

感谢您的帮助。

0 个答案:

没有答案