c# - Unity System.Drawing内部缓冲区溢出异常

标签 c# unity-game-engine system.drawing unity3d-gui

目标

从 URL 获取统一工作的 gif,我目前正在使用 WWW 类。我目前正在获取一个 byte[] 并将其转换为 System.Drawing.Image。 这适用于编辑器,但不适用于任何构建

错误:

第 111 行程序集“System.Drawing.Image”中的“类型加载异常:无法加载类型”System.IO.InternalBufferOverflowException

为什么?

它与 System.Drawing.Image.FromStream 内置方法有关,Unity 由于某种原因不喜欢它。其他选项是 .FromFile 和 .FromHBitMap,我不知道如何使用 HBitMap,但回到我原来的计划,.FromFile 对我来说无法使用。

整个代码

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using UnityEngine;
using System.IO;
using UnityEngine.UI;
using System.Collections;

public class AnimatedGifDrawerBack : MonoBehaviour
{
    public string loadingGifPath;
    public float speed = 1;
    public Vector2 drawPosition;
    public string pName;

    public float width;
    public float height;
    public float percentage;
    public GameObject positionPlaceHolderGO;
    public Vector2 positionPlaceHolder;
    public Text debugText;
    private SpriteImageArray sia;
    private string url;
    private WWW www;
    public bool finishedWWW = false;
    public bool hasWWW = false;
    public bool canOnGUI = false;

    List<Texture2D> gifFrames = new List<Texture2D>();

    void Start()
    {


        percentage = 1.3f;
        positionPlaceHolderGO = GameObject.FindGameObjectWithTag("PBLPlace");
        positionPlaceHolder = positionPlaceHolderGO.transform.position;

    }

    void Update()
    {
        while (hasWWW == false)
        {
            Debug.Log("in while loop");
            if (this.GetComponent<PokemonCreatorBack>().name == "")
            {

            }
            else
            {
                debugText.text = "Name Found";
                url = "www.pkparaiso.com/imagenes/xy/sprites/animados-espalda/" + this.GetComponent<PokemonCreatorBack>().PokemonName.ToLower() + ".gif";

                StartCoroutine(WaitForRequest(positionPlaceHolderGO, url));
                hasWWW = true;
                debugText.text = "hawWWW = true";
            }
        }
    }

    void OnGUI()
    {
        height = (float)Screen.height - 80f / percentage;

        //GUI.DrawTexture (new Rect (Screen.width-width, Screen.height - height, gifFrames [0].width * percentage, gifFrames [0].height * percentage), gifFrames [(int)(Time.frameCount * speed) % gifFrames.Count]);
        if (canOnGUI)
            GUI.DrawTexture(new Rect(positionPlaceHolder.x, positionPlaceHolder.y, gifFrames[0].width * percentage, gifFrames[0].height * percentage), gifFrames[(int)(Time.frameCount * speed) % gifFrames.Count]);

    }

    IEnumerator WaitForRequest(GameObject go, string url)
    {
        www = new WWW(url);
        yield return www;
        if (www.error == null)
        {
            Debug.Log("WWW Ok!: " + www.texture.name);
        }
        else
        {
            Debug.Log("WWW Error: " + www.error);
        }
        debugText.text = "finishedWWW = true";
        finishedWWW = true;
    }

    public System.Drawing.Image ByteArrayToImage(byte[] byteArrayIn)
    {
        if (finishedWWW == false)
        {
            Debug.Log("Called too early");
        }
        if (byteArrayIn == null)
        {
            Debug.Log("Null byte array");
            return null;
        }
        Debug.Log("Bytra array in length: " + byteArrayIn.GetLongLength(0));
        MemoryStream ms = new MemoryStream(byteArrayIn);
        System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);     //MAIN SOURCE OF ERROR HERE
        finishedWWW = true;
        debugText.text = "System.Image Created";
        return returnImage;
    }

    public void loadImage()
    {
        Debug.Log("Called Load Image BACK");
        debugText.text = "Called Load Image BACK";
        System.Drawing.Image gifImage = ByteArrayToImage(www.bytes);


        FrameDimension dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
        int frameCount = gifImage.GetFrameCount(dimension);
        for (int i = 0; i < frameCount; i++)
        {
            gifImage.SelectActiveFrame(dimension, i);
            Bitmap frame = new Bitmap(gifImage.Width, gifImage.Height);
            System.Drawing.Graphics.FromImage(frame).DrawImage(gifImage, Point.Empty);
            Texture2D frameTexture = new Texture2D(frame.Width, frame.Height);
            for (int x = 0; x < frame.Width; x++)
                for (int y = 0; y < frame.Height; y++)
                {
                    System.Drawing.Color sourceColor = frame.GetPixel(x, y);
                    frameTexture.SetPixel(frame.Width - 1 + x, -y, new Color32(sourceColor.R, sourceColor.G, sourceColor.B, sourceColor.A)); // for some reason, x is flipped
                }
            frameTexture.Apply();
            gifFrames.Add(frameTexture);
        }
        Debug.Log("Starting ON GUI!");
        debugText.text = "Starting OnGUI";
        canOnGUI = true;
    }
}

想法

  1. byteArrayIn.GetLongLength(0) 最多返回80,000。
  2. 最后一条调试语句称为“Image Loading BACK”。
  3. 如果有必要,我会写我自己的火流,如果有必要,有人可以给我指出写作方向。
  4. 我认为主要的解决方法是处理 Image.FromStream()。
  5. 场景中有两个这样的东西。

欢迎所有想法或解决方案,我真的希望我知道如何解决这个错误,以便我可以与 Unity 社区更多地分享。

最佳答案

今天早上我们遇到了同样的问题。

应用程序未在 System.IO 命名空间中找到 System.Drawing.Image 所需的类型。

缺失的类型显然已从构建过程中打包的 system.dll 中删除。

要解决此问题,您需要复制 Unity 生成的 System.dll 并将其替换为原始 mono System.dll

在您的构建中,将 projectName_Data\Managed\System.dll 替换为 Unity Mono 安装文件夹中的 System.dll:

Editor\Data\Mono\lib\mono\2.0(相对于 Unity 安装文件夹的根目录)。

希望对你有帮助!

关于c# - Unity System.Drawing内部缓冲区溢出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33018740/

相关文章:

c# - 如何使用反射来简化构造函数和比较?

c# - DotNetZip 库从一个 zip 文件读取到另一个

c# - 空引用异常 : unity3d

c# - Unity - 将 Leped 位置反转回原始位置

ios - 统一 5 和 IL2CPP : cannot build

c# - 如何修复 System.Drawing.dll 中的控制台应用程序异常 "' System.ArgumentException'

.net - 为什么用 System.Drawing 创建的 JPEG 图像比原始位图大?

c# - 正则表达式,从分隔字符串中删除重复路径

c# - 用户控件上 UpdatePanel 的替代品(ASCX 页面)

c# - System.Drawing 对于 2D 游戏编程来说足够快吗?