Unity实用功能之浏览并加载本地图片

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战web

概述

如今不少软件,网站都有更换头像,上传图片等功能,本篇文章主要讲解一下在Unity中,如何浏览本地图片文件,并将其加载到untiy中并显示出来。大致上分为两个步骤:浏览本地文件、加载本地文件(其余格式文件原理相同)数组

思路分析

总体的思路是:markdown

  1. 调用系统的文件窗口(打开资源管理器,进行图片资源的浏览)
  2. 经过资源管理器获取到的图片路径,将图片加载出

加载本地图片的方式:app

  • 使用WWW进行图片加载(此方法适用旧版Unity)
  • 使用UnityWebRequest进行图片加载(此方法使用于高版本Unity)
  • 以IO方式进行加载图片

功能实现

调用系统文件窗口

引用Comdlg32.dll系统类库,调用GetOpenFileName方法实现窗口打开功能。具体实现代码以下:框架

public class WindowDll
{
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    public static bool GetOpenFileName1([In, Out] OpenFileName ofn)
    {
        return GetOpenFileName(ofn);
    }
}
复制代码

光有这一段代码还不足够,还须要声明原型,设置参数,建立OpenFileName类,并为每一个结构元素声明一个类成员。具体可参照微软官方的.NET 框架高级开发文档,本文中使用到的参数以下:oop

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
    public int structSize = 0;
    public IntPtr dlgOwner = IntPtr.Zero;
    public IntPtr instance = IntPtr.Zero;
    public String filter = null;
    public String customFilter = null;
    public int maxCustFilter = 0;
    public int filterIndex = 0;
    public String file = null;
    public int maxFile = 0;
    public String fileTitle = null;
    public int maxFileTitle = 0;
    public String initialDir = null;
    public String title = null;
    public int flags = 0;
    public short fileOffset = 0;
    public short fileExtension = 0;
    public String defExt = null;
    public IntPtr custData = IntPtr.Zero;
    public IntPtr hook = IntPtr.Zero;
    public String templateName = null;
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;
}
复制代码

到此,调用系统文件窗口文件就实现了。post

打开窗口获取文件路径

上面打开窗口方法已经写好了,接下来要编写一个按钮点击事件,经过按钮,调用上述方法,打开要加载的图片并获取图片位置:动画

OpenFileName ofn = new OpenFileName();
ofn.structSize = Marshal.SizeOf(ofn);
ofn.filter = "图片文件(*.jpg*.png)\0*.jpg;*.png";
ofn.file = new string(new char[256]);
ofn.maxFile = ofn.file.Length;
ofn.fileTitle = new string(new char[64]);
ofn.maxFileTitle = ofn.fileTitle.Length;
//默认路径
string path = Application.streamingAssetsPath;
path = path.Replace('/', '\\');
ofn.initialDir = path;
ofn.title = "Open Project";
ofn.defExt = "JPG";
//注意 一下项目不必定要全选 可是0x00000008项不要缺乏
ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;
//上一行代码对应以下
//OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR
//点击Windows窗口时开始加载选中的图片
if (WindowDll.GetOpenFileName(ofn))
{
    Debug.Log("Selected file with full path: " + ofn.file);
}
复制代码

上述代码中,有几个主要参数:网站

  • ofn.initialDir:是打开的窗口的默认路径
  • ofn.defExt:打开窗口中要显示的文件的类型
  • ofn.file:这个是主要的,这个是选中的图片返回的路径参数,包括路径+文件名所有在一块儿。

其余的参数很好理解,只要设置成对应的参数便可。url

加载图片方法一---使用WWW加载

此方法使用于低版本Unity使用,高版本Unity虽然可使用,可是会报过期的警告。www加载方式主要是将图片加载为Texture2D。而咱们要将图片显示在Image上,Image使用的是Sprite,因此咱们须要将图片转换为sprite在赋值给图片。如下方法是将图片加载为Texture2D。

IEnumerator Load(string path)
{
    WWW www = new WWW("file:///" + path);
    yield return www;
    if (www != null && string.IsNullOrEmpty(www.error))
    {
        //获取Texture
        Texture2D texture = www.texture;
    }
}
复制代码

在获取到texture后,根据获取的Texture建立一个sprite

Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
复制代码

接着就能够将图片赋值到Image身上,有事图片会比Image大或小,这是可能有的人须要使用原始图片大小,这是就须要将图片尺寸设置为原始尺寸

image.SetNativeSize();

加载图片方法二---使用UnityWebRequest加载

方法一加载本地图片文件是经过www加载,可是高版本Unity已经不支持这个API了,采用了更高级的API。根据官方文档介绍,采用UnityWebRequest代替。命名空间一样是NetWorking,整体没有太大变化,和WWW加载几乎相同,只是代码写法略有差异,具体方法以下代码

IEnumerator Load(string path)
{
    UnityWebRequest request = UnityWebRequestTexture.GetTexture(path);
    yield return request.SendWebRequest();
    if (request.isHttpError || request.isNetworkError)
    {
        Debug.Log(request.error);
    }
    else
    {
        Texture tt = DownloadHandlerTexture.GetContent(request);
        //根据获取的Texture建立一个sprite
        Sprite sprite = Sprite.Create((Texture2D)tt, new Rect(0, 0, tt.width, tt.height), new Vector2(0.5f, 0.5f));
        //将sprite显示在图片上
        image.sprite = sprite;
        //图片设置为原始尺寸
        image.SetNativeSize();
    }  
}  
复制代码

加载图片方法三---使用IO方式读取文件

流:
流的定义:流是在内存中开辟内存地址,而后将文件中的数据存入流,在内存中(流中)对文本内容进行更改,再保存回文件。
流的关键字:FileStream,应用到FileStream就是使用流
首先须要引用命名空间using System.IO;using System.IO.Compression; 具体代码为:

private void LoadByIo(string url)
    {
        //建立文件读取流
        FileStream fileStream = new FileStream(url, FileMode.Open, FileAccess.Read);
        //建立文件长度缓冲区
        byte[] bytes = new byte[fileStream.Length];
        //读取文件
        fileStream.Read(bytes, 0, (int)fileStream.Length);

        //释放文件读取流
        fileStream.Close();
        //释放本机屏幕资源
        fileStream.Dispose();
        fileStream = null;

        //建立Texture
        int width = 300;
        int height = 372;
        Texture2D texture = new Texture2D(width, height);
        texture.LoadImage(bytes);

        //建立Sprite
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
        //将sprite显示在图片上
        image.sprite = sprite;
        //图片设置为原始尺寸
        image.SetNativeSize();
    }
复制代码

注意:经过Read获取文件的内容赋值给syte数组的时候同时会保存到流内,再经过write写入相同的内容到流中就会有双倍的原文件内容,因此经过Read读取流内数据后只须要write新的数据进入流中就能将文件自身的数据和新的数据同时从流写入到文件中。

效果展现

三种加载方法效果是相同的

动画.gif

写在最后

全部分享的内容均为做者在平常开发过程当中使用过的各类小功能点,分享出来也变相的回顾一下,若有写的很差的地方还请多多指教。Demo源码会在以后整理好以后分享给你们。

相关文章
相关标签/搜索