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源碼會在以後整理好以後分享給你們。

相關文章
相關標籤/搜索