Unity 中加载 Gif 文件

2019/11/05 Unity

方法1

通过 System.Drawing.dll1实现

导入 DLL文件到项目里

Mac

\Editor\Data\Mono\lib\mono\2.0\System.Drawing.dll

Window

/Applications/Unity/Unity.app/Contents/Mono/lib/mono/2.0/System.Drawing.dll

实现

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

/// <summary>
/// 使用SetGifPath(string path)传入GIF图片路径
/// </summary>
public class GifPlayer : MonoBehaviour
{
    // 帧数   
    private const float Fps = 24;
    private UnityEngine.UI.Image _image;
    public List<Texture2D> _tex2DList = new List<Texture2D>();
    private float _time;

    private void Awake()
    {
        _image = GetComponent<UnityEngine.UI.Image>();
    }

    public void LoadGif(string path)
    {
        var image = System.Drawing.Image.FromFile(path);
        _tex2DList = Gif2Texture2D(image);
    }

    private int _framCount;

    /// <summary>
    /// Gif转Texture2D
    /// </summary>
    /// <param name="image"> System.Image</param>
    /// <returns>Texture2D集合</returns>
    private List<Texture2D> Gif2Texture2D(System.Drawing.Image image)
    {
        var tex = new List<Texture2D>();
        if (image == null) return tex;
        // 图片构成有两种形式: 1、多页(.gif)  2、多分辨率
        Debug.Log("image对象的dimenson数:" + image.FrameDimensionsList.Length);
        // 根据指定的GUID创建一个提供获取图像框架维度信息的实例
        var frameDimension = new FrameDimension(image.FrameDimensionsList[0]);
        _framCount = image.GetFrameCount(frameDimension);
        Debug.Log(_framCount);
        for (var i = 0; i < _framCount; i++)
        {
            image.SelectActiveFrame(frameDimension, i);
            var framBitmap = new Bitmap(image.Width, image.Height);
            using (var newGraphics = System.Drawing.Graphics.FromImage(framBitmap))
            {
                newGraphics.DrawImage(image, Point.Empty);
            }

            var frameTexture2D = new Texture2D(framBitmap.Width, framBitmap.Height, TextureFormat.ARGB32, true);
            frameTexture2D.LoadImage(Bitmap2Byte(framBitmap));
            tex.Add(frameTexture2D);
        }

        return tex;
    }

    /// <summary>
    /// Bitmap转Byte
    /// </summary>
    /// <param name="bitmap">Bitmap</param>
    /// <returns>byte数组</returns>
    private byte[] Bitmap2Byte(Bitmap bitmap)
    {
        using (var stream = new MemoryStream())
        {
            bitmap.Save(stream, ImageFormat.Png);
            var data = new byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(data, 0, Convert.ToInt32(stream.Length));
            return data;
        }
    }


    private void Update()
    {
        if (_tex2DList == null || _tex2DList.Count <= 0) return;
        if (_framCount < 2) return;
        _time += Time.deltaTime;
        var index = (int) (_time * Fps) % _tex2DList.Count;
        if (_image != null)
        {
            _image.sprite = Sprite.Create(_tex2DList[index],
                new Rect(0, 0, _tex2DList[index].width, _tex2DList[index].height), new Vector2(0.5f, 0.5f));
        }
    }
}

方法2

https://github.com/WestHillApps/UniGif

加载方式

以上两种方法都需要直接通过文件的bytes数据来解析,但是当使用Assetbundle、Resource、或 AssetDatabase.LoadAssetAtPath时,无法直接读取 bytes 数据。而且gif文件默认会被Unity加载成 Texture2D。可以将gif图片命名成 txt 文件,读取成TextAssets格式。然后可以通过 textAsset.bytes 拿到需要的原数据。

var textAsset= AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/icon/achieve/test1.txt");