好久不写博客了,一是因为结婚以后变得越来越懒,二是因为新冠疫情期间忙着换工作,程序转产品,产品干了多半年以后,又从产品转回了程序员,在这里也给想转岗的童鞋一些建议,不要盲目转岗,不要觉得产品经理不就是每天开开会,写写文档吗,的确,你想的没错,他们就是每天的日子就是这样潇洒,不过这并不意味着产品经理这个岗位适合每个人,个人感觉人人都是产品经理的口号,的确是一个大坑,既破坏了产品行业的市场,也低估了产品经理岗位的难度。如果真的打算转岗,也要拿出一段时间,学习新的岗位所需要的基本技能,然后做好受打击的准备,新的岗位,就意味着从新开始,之前的经验将不再适应,从受人尊敬的技术大牛,到处处受气的产品小白,这种落差一定要有心理准备,薪资肯定也会降。我不只一次听到我周围的同事说:唉,程序员再干两年,挣够钱就转产品。
我要说的是,产品不是养老,回家种地才是。
年纪大了,就爱感慨,废话少叙,步入正题。
1、关于为什么要将图片转成DXT格式,我这里做了一些统计:
3、新建空工程下验证加载一张5376*2688的jpg图片,图片为43352064字节,所以理论上应占内存41.3MB,压缩后图片7225344字节,理论上应占内存6.89MB a)直接加载耗时 179.26 毫秒,Profiler显示Textures增加了96.4Mb内存 b)直接加载并压缩耗时 394.46毫秒,Profiler显示Textures增加了13.8Mb内存。 c)加载保存在本地的压缩后的byte[]耗时 36.50到52.91 毫秒之间。Profiler显示Textures增加了13.8Mb内存
由此我们可以得出结论,将图片压缩后的byte[]保存在本地,然后直接读取该byte[]速度最快,从Profiler上看的内存是理论占用内存的二倍(在新建的空工程下)。
这或许将会对我们的程序优化有很大帮助,我们要做的就是,在下载完图片,将图片压缩成DXT格式,我们就能得到更加流畅的程序体验。
2、那么我们需要怎么做呢
其实很简单,按照Unity官方文档的说法,Texture2D.Compress就可以搞定
可是好不好用,试了才知道,这就引出了上文提到的统计。
加载完图片,再调用Compress方法进行压缩,非常耗时,最终的结果是程序卡顿,当然也会有杠精说用协程异步加载不就好了吗,你说的都对,咱不跟你抬杠。
有心的童鞋就会想到,我们为什么不将调用Compress方法进行压缩后的数据保存起来,以后每次只加载图片压缩后的数据呢,从上文提到的统计中可以看出,
这种思路的确不失为一种比较好的方式。
3、具体实现
前戏铺垫的有点长,终于到重点,打字也累了直接上代码,真的是越来越懒了
/// <summary> /// 图片压缩成DXT格式 /// </summary> /// <param name="path"></param> public static void CompressDXT(string path) { //读图片 FileStream readStream = new FileStream(path, FileMode.Open, FileAccess.Read); readStream.Seek(0, SeekOrigin.Begin); byte[] bytes = new byte[readStream.Length]; readStream.Read(bytes, 0, (int)readStream.Length); readStream.Close(); readStream.Dispose(); Texture2D texture2D = new Texture2D(600, 300, TextureFormat.ARGB32, false); texture2D.LoadImage(bytes); texture2D.Compress(true);//压缩 byte[] imgWidth = BitConverter.GetBytes(texture2D.width); byte[] imgHeight = BitConverter.GetBytes(texture2D.height); byte[] imgformat = BitConverter.GetBytes((int)texture2D.format); byte[] imgData = texture2D.GetRawTextureData(); //将压缩后的图片写入本地 FileStream writeStream = new FileStream(path + "_dxt", FileMode.OpenOrCreate, FileAccess.ReadWrite); writeStream.Seek(0, SeekOrigin.Begin); writeStream.Write(imgWidth, 0, 4);//一个int占4个字节 writeStream.Seek(4, SeekOrigin.Begin); writeStream.Write(imgHeight, 0, 4); writeStream.Seek(8, SeekOrigin.Begin); writeStream.Write(imgformat, 0, 4); writeStream.Seek(12, SeekOrigin.Begin); writeStream.Write(imgData, 0, imgData.Length); writeStream.Close(); writeStream.Dispose(); if (File.Exists(path)) File.Delete(path); }
/// <summary> /// 加载DXT格式 /// </summary> /// <param name="loadpath"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="type"></param> /// <param name="autoCubeSize"></param> /// <returns></returns> public static Texture2D LoadDXT(string loadpath) { if (!File.Exists(loadpath)) return null; FileStream fileStream = new FileStream(loadpath, FileMode.Open, FileAccess.Read); byte[] imgWidth = new byte[4]; byte[] imgHeight = new byte[4]; byte[] imgformat = new byte[4]; byte[] imgData = new byte[(int)fileStream.Length - 12]; fileStream.Seek(0, SeekOrigin.Begin); fileStream.Read(imgWidth, 0, 4); fileStream.Seek(4, SeekOrigin.Begin); fileStream.Read(imgHeight, 0, 4); fileStream.Seek(8, SeekOrigin.Begin); fileStream.Read(imgformat, 0, 4); fileStream.Seek(12, SeekOrigin.Begin); fileStream.Read(imgData, 0, (int)fileStream.Length - 12); fileStream.Close(); fileStream.Dispose(); //创建Texture Texture2D texture2D = new Texture2D(BitConverter.ToInt32(imgWidth, 0), BitConverter.ToInt32(imgHeight, 0), (TextureFormat)BitConverter.ToInt32(imgformat, 0), false); texture2D.LoadRawTextureData(imgData); texture2D.Apply(); Resources.UnloadUnusedAssets(); return texture2D; }
Jason_c原创博客,请大家多多支持,转载标明出处