unity 加载网络图片
摘要:利用Http加载网络图片。
解决思路:
1、直接用unity 自带的www加载,在高版本www已经过时了。
2、本文直接使用万能的文件流加载。
(1)使用System.Net.HttpWebRequest 请求网络流。
(2)利用System.Drawing这个dll把网络流装载到内存。可以获取远程网络图片的基本信息,图片宽高,格式等。如果已经知道远程图片数据,可以先把网络流拷贝到内存,直接对流进行操作。
(3)Texture2D.LoadImage显示图片
废话不多说,直接上代码
获取网络图片二进制数据:
1 public struct RemoteImageMessage 2 { 3 public int Width; 4 5 public int Height; 6 7 public byte[] DataSource; 8 } 9 10 public static class ImageDownloadHelper 11 { 12 /// <summary> 13 /// 获取远程图片 14 /// </summary> 15 /// <param name="imgPath"></param> 16 /// <param name="complete"></param> 17 public static void GetImage(string imgPath, Action<RemoteImageMessage> complete) 18 { 19 System.Threading.Tasks.Task.Run(() => 20 { 21 RemoteImageMessage remoteImageMessage = new RemoteImageMessage(); 22 try 23 { 24 System.Net.HttpWebRequest webRequest = System.Net.WebRequest.CreateHttp(imgPath); 25 using (var response = webRequest.GetResponse()) 26 { 27 if (response.ContentLength != 0) 28 { 29 System.IO.Stream stream = response.GetResponseStream(); 30 System.Drawing.Image image = System.Drawing.Image.FromStream(stream); 31 remoteImageMessage.Width = image.Width; 32 remoteImageMessage.Height = image.Height; 33 var bytes = ImageToBytes(image); 34 remoteImageMessage.DataSource = bytes; 35 stream.Close(); 36 stream.Dispose(); 37 } 38 } 39 } 40 catch (Exception ex) 41 { 42 Debug.LogError("加载图片出错!" + ex); 43 } 44 finally 45 { 46 complete?.Invoke(remoteImageMessage); 47 } 48 }); 49 } 50 51 /// <summary> 52 /// Image 转bytes 53 /// </summary> 54 /// <param name="image"></param> 55 /// <returns></returns> 56 private static byte[] ImageToBytes(System.Drawing.Image image) 57 { 58 System.Drawing.Imaging.ImageFormat format = image.RawFormat; 59 using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) 60 { 61 if (format.Equals(System.Drawing.Imaging.ImageFormat.Jpeg)) 62 { 63 image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 64 } 65 else if (format.Equals(System.Drawing.Imaging.ImageFormat.Png)) 66 { 67 image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); 68 } 69 else if (format.Equals(System.Drawing.Imaging.ImageFormat.Bmp)) 70 { 71 image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); 72 } 73 else if (format.Equals(System.Drawing.Imaging.ImageFormat.Gif)) 74 { 75 image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif); 76 } 77 else if (format.Equals(System.Drawing.Imaging.ImageFormat.Icon)) 78 { 79 image.Save(ms, System.Drawing.Imaging.ImageFormat.Icon); 80 } 81 byte[] buffer = new byte[ms.Length]; 82 //Image.Save()会改变MemoryStream的Position,需要重新Seek到Begin 83 ms.Seek(0, System.IO.SeekOrigin.Begin); 84 ms.Read(buffer, 0, buffer.Length); 85 return buffer; 86 } 87 } 88 89 }
在unity中显示
1 public class ImageLoaderHeler : MonoBehaviour 2 { 3 private RawImage rawImage = null; 4 5 private string[] imageUrl = new string[] 6 { "http://t8.baidu.com/it/u=2247852322,986532796&fm=79&app=86&f=JPEG?w=1280&h=853", 7 "http://t9.baidu.com/it/u=3363001160,1163944807&fm=79&app=86&f=JPEG?w=1280&h=830", 8 "http://t9.baidu.com/it/u=583874135,70653437&fm=79&app=86&f=JPEG?w=3607&h=2408", 9 "http://t9.baidu.com/it/u=2268908537,2815455140&fm=79&app=86&f=JPEG?w=1280&h=719", 10 "http://t7.baidu.com/it/u=1179872664,290201490&fm=79&app=86&f=JPEG?w=1280&h=854", 11 "http://t9.baidu.com/it/u=3923875871,1613462878&fm=79&app=86&f=JPEG?w=1280&h=854", 12 "http://t9.baidu.com/it/u=3949188917,63856583&fm=79&app=86&f=JPEG?w=1280&h=875", 13 "http://t7.baidu.com/it/u=1355385882,1155324943&fm=79&app=86&f=JPEG?w=1280&h=854", 14 "http://t8.baidu.com/it/u=2857883419,1187496708&fm=79&app=86&f=JPEG?w=1280&h=763", 15 "http://t7.baidu.com/it/u=830740827,3648735644&fm=79&app=86&f=JPEG?w=1280&h=853", 16 "http://t8.baidu.com/it/u=198337120,441348595&fm=79&app=86&f=JPEG?w=1280&h=732", 17 "http://t9.baidu.com/it/u=1577456063,1344044640&fm=79&app=86&f=JPEG?w=1280&h=853", 18 "http://t8.baidu.com/it/u=2678662753,1297312162&fm=79&app=86&f=JPEG?w=1181&h=787", 19 "http://t8.baidu.com/it/u=2148738019,2920001333&fm=79&app=86&f=JPEG?w=1181&h=788", 20 "http://t9.baidu.com/it/u=1373840141,993565751&fm=79&app=86&f=JPEG?w=1181&h=788" 21 }; 22 23 // Start is called before the first frame update 24 void Start() 25 { 26 rawImage = GetComponent<RawImage>(); 27 //InvokeRepeating("Test", 3, 0.5f); 28 } 29 30 31 private int index = 0; 32 33 private void Test() 34 { 35 if (index >= imageUrl.Length) 36 { 37 index = 0; 38 } 39 LoadImage(imageUrl[index++]); 40 } 41 42 private void LoadImage(string imagePath) 43 { 44 var start = DateTime.Now; 45 Debug.LogError("图片数据开始加载!"); 46 ImageDownloadHelper.GetImage(imagePath, (image) => 47 { 48 ThreadCrossor.GetInstance()?.AddTaskToMainThread(() => 49 { 50 var ori = rawImage.texture; 51 if (ori != null) 52 { 53 DestroyImmediate(ori); 54 rawImage.texture = null; 55 } 56 Debug.LogError($"图片尺寸{image.Width},{image.Height}"); 57 Texture2D texture2D = new Texture2D(image.Width, image.Height); 58 texture2D.LoadImage(image.DataSource); 59 rawImage.texture = texture2D; 60 }); 61 Debug.LogError($"完成图片加载!加载时间:{(DateTime.Now - start).TotalSeconds}s"); 62 }); 63 } 64 65 66 // Update is called once per frame 67 void Update() 68 { 69 70 } 71 }
写了一个简单的跨线程交互的类
public class ThreadCrossor : MonoBehaviour { private static ThreadCrossor threadCrossor = null; List<Action> actions = new List<Action>(); public static ThreadCrossor GetInstance() { return threadCrossor; } /// <summary> /// 往主进程添加任务 /// </summary> /// <param name="action"></param> public void AddTaskToMainThread(Action action) { lock (actions) { actions.Add(action); } } // Start is called before the first frame update void Start() { threadCrossor = this; } // Update is called once per frame void Update() { lock (actions) { if (actions.Count > 0) { foreach(var action in actions) { action?.Invoke(); } actions.Clear(); } } } }
效果如下: