如何使用?

界面展示:
image.png
介绍: 是一个脚本(从别人源码改进了一点点)
作用:(√这么多好处,那为什么不用呢?)
1.对多张贴图进行通道选择,然后在指定文件夹目录创建并制成一张复合贴图
①对减少贴图资源有大用!(省资源)
②不用出去PS那么麻烦制作复合贴图了,泪目(省时间)
2.如果想单纯缩放图片,不在意图片有点损耗的话,可以通过此方式缩放图片
操作如下:
①把脚本拖入任何一个GameObject(游戏物体中)
②把图片拖入,选择好“相关选项”
③右键脚本处,可选择“选择保存路径”即可定位保存路径(自己输入也行)
④右键脚本出,选择“制作复合图像并保存”即可完成操作

代码模块

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System.IO;
  6. public class CombineIntoCompositeMap : MonoBehaviour
  7. {
  8. public enum Channel
  9. {
  10. R通道 = 0,
  11. G通道 = 1,
  12. B通道 = 2,
  13. A通道 = 3
  14. };
  15. public enum RGB_To_Gray_Mode
  16. {
  17. 平均值法 = 0,
  18. OpenCV彩色转灰度 = 1
  19. }
  20. [Header("请为RGBA通道选择相应图像")]
  21. public Texture2D texR;//第一张拖入图
  22. public Channel texRChannel = Channel.取R通道;
  23. public Texture2D texG;//第二张拖入图
  24. public Channel texGChannel = Channel.取R通道;
  25. public Texture2D texB;//第三张拖入图
  26. public Channel texBChannel = Channel.取R通道;
  27. public Texture2D texA;//第四张拖入图
  28. public Channel texAChannel = Channel.取R通道;
  29. [Header("输出图片尺寸(像素)")]
  30. public Vector2 imageWH = new Vector2(256,256);//自定义图片宽高
  31. [Header("带A通道?")]
  32. public bool isAlpha = true;//是否开启A通道
  33. [Header("输出黑白图?")]
  34. public bool isBlackAndWhite = false;//是否为黑白图
  35. [Header("输出黑白图模式选择")]
  36. public RGB_To_Gray_Mode GrayMode = RGB_To_Gray_Mode.平均值法;
  37. [Header("输出图片名称")]
  38. public string texName = "Enter Your Name!";//最终图片名称
  39. [Header("输出图片路径")]
  40. public string customPath = "";//目标路径
  41. //[Header("尾部命名序号(自动+1);指定序号覆盖原数据")]
  42. //public int serial = 1;
  43. [Header("图片后缀")]
  44. public string suffix = "_Combined";
  45. [Header("在此材质上看效果")]
  46. public Material mat;
  47. public string matTexName = "_MainTex";
  48. private Texture2D texAllCombined;//所有图片结合体
  49. private Color[] colorR;//TexR临时颜色
  50. private Color[] colorG;//TexG临时颜色
  51. private Color[] colorB;//TexB临时颜色
  52. private Color[] colorA;//TexA临时颜色
  53. private Color[] colorAllCombined;//最终输出相关颜色
  54. private Texture2D R;
  55. private Texture2D G;
  56. private Texture2D B;
  57. private Texture2D A;
  58. void SetTexImport(Texture2D inputTex)//修改Texture2D导入设置
  59. {
  60. string path = AssetDatabase.GetAssetPath(inputTex);
  61. TextureImporter tex = AssetImporter.GetAtPath(path) as TextureImporter;
  62. //存储 TextureImporter 的平台特定设置。
  63. TextureImporterPlatformSettings set = new TextureImporterPlatformSettings();
  64. tex.isReadable = true;//允许读取纹理数据
  65. AssetDatabase.ImportAsset(path);
  66. set.format = TextureImporterFormat.RGBA32;
  67. tex.SetPlatformTextureSettings(set);
  68. //重新导入资源,否则更改并未生效
  69. //如资源未执行重新导入,则会在项目保存时自动导入、生效
  70. AssetDatabase.ImportAsset(path);
  71. }
  72. void Save(Color[] colors)//创建图像并保存为基础图像
  73. {
  74. TextureFormat _texFormat;
  75. if (isAlpha){
  76. _texFormat = TextureFormat.ARGB32;
  77. }else{
  78. _texFormat = TextureFormat.RGB24;
  79. }
  80. Texture2D tex = new Texture2D((int)imageWH.x, (int)imageWH.y, _texFormat, false);//创建特定宽高图片
  81. tex.SetPixels(colors);
  82. tex.Apply();//实际应用任何先前的 SetPixel 和 SetPixels 更改
  83. byte[] bytes;
  84. bytes = tex.EncodeToPNG();//转化为.PNG图片(返回byte[])
  85. //①序号方式
  86. //string fileName = texName + "_" + serial;
  87. //serial += 1;
  88. //②后缀方式
  89. string fileName = texName + "_" + suffix;
  90. //创建新文件,将指定字节数组写入此文件(如文件已存在,则会覆盖)
  91. File.WriteAllBytes(customPath + "/" + fileName + ".png", bytes);
  92. Debug.Log("PNG图像:" + fileName + "已保存到" + customPath);
  93. AssetDatabase.Refresh();//导入所有更改资源
  94. }
  95. void SetTexSize()//设置图片尺寸
  96. {
  97. if(texR != null)
  98. {
  99. Debug.Log("texR!=null");
  100. SetTexImport(texR);//修改Tex导入设置
  101. R = texR;
  102. string path = AssetDatabase.GetAssetPath(R);
  103. R = ScaleTexture(texR, imageWH.x, imageWH.y);//将双线性过滤后的缩放图像 赋值给R
  104. R.Apply();//实际应用任何先前的 SetPixel 和 SetPixels 更改
  105. TextureImporter tex = AssetImporter.GetAtPath(path) as TextureImporter;
  106. TextureImporterPlatformSettings temp = new TextureImporterPlatformSettings();
  107. temp.format = TextureImporterFormat.Automatic;
  108. tex.SetPlatformTextureSettings(temp);
  109. tex.isReadable = false;
  110. AssetDatabase.ImportAsset(path);
  111. }
  112. if (texG != null)
  113. {
  114. SetTexImport(texG);//修改Tex导入设置
  115. G = texG;
  116. string path = AssetDatabase.GetAssetPath(G);
  117. G = ScaleTexture(texG, imageWH.x, imageWH.y);//将双线性过滤后的缩放图像 赋值给G
  118. G.Apply();//实际应用任何先前的 SetPixel 和 SetPixels 更改
  119. TextureImporter tex = AssetImporter.GetAtPath(path) as TextureImporter;
  120. TextureImporterPlatformSettings temp = new TextureImporterPlatformSettings();
  121. temp.format = TextureImporterFormat.Automatic;
  122. tex.SetPlatformTextureSettings(temp);
  123. tex.isReadable = false;
  124. AssetDatabase.ImportAsset(path);
  125. }
  126. if (texB != null)
  127. {
  128. SetTexImport(texB);//修改Tex导入设置
  129. B = texB;
  130. string path = AssetDatabase.GetAssetPath(B);
  131. B = ScaleTexture(texB, imageWH.x, imageWH.y);//将双线性过滤后的缩放图像 赋值给B
  132. B.Apply();//实际应用任何先前的 SetPixel 和 SetPixels 更改
  133. TextureImporter tex = AssetImporter.GetAtPath(path) as TextureImporter;
  134. TextureImporterPlatformSettings temp = new TextureImporterPlatformSettings();
  135. temp.format = TextureImporterFormat.Automatic;
  136. tex.SetPlatformTextureSettings(temp);
  137. tex.isReadable = false;
  138. AssetDatabase.ImportAsset(path);
  139. }
  140. if (texA != null)
  141. {
  142. SetTexImport(texA);//修改Tex导入设置
  143. A = texA;
  144. string path = AssetDatabase.GetAssetPath(A);
  145. A = ScaleTexture(texA, imageWH.x, imageWH.y);//将双线性过滤后的缩放图像 赋值给A
  146. A.Apply();//实际应用任何先前的 SetPixel 和 SetPixels 更改
  147. TextureImporter tex = AssetImporter.GetAtPath(path) as TextureImporter;
  148. TextureImporterPlatformSettings temp = new TextureImporterPlatformSettings();
  149. temp.format = TextureImporterFormat.Automatic;
  150. tex.SetPlatformTextureSettings(temp);
  151. tex.isReadable = false;
  152. AssetDatabase.ImportAsset(path);
  153. }
  154. }
  155. [ContextMenu("制作复合图像并保存")]
  156. void CombineImage()
  157. {
  158. colorR = new Color[0];
  159. colorG = new Color[0];
  160. colorB = new Color[0];
  161. colorA = new Color[0];
  162. colorAllCombined = new Color[0];
  163. SetTexSize();//设置图片尺寸
  164. texAllCombined = new Texture2D((int)imageWH.x, (int)imageWH.y);//图片通道结合体
  165. //将图像像素颜色信息赋给color[]
  166. if (texR != null)
  167. {
  168. colorR = R.GetPixels();
  169. colorAllCombined = R.GetPixels();
  170. }
  171. if (texG != null)
  172. {
  173. colorG = G.GetPixels();
  174. }
  175. if (texB != null)
  176. {
  177. colorB = B.GetPixels();
  178. }
  179. if (texA != null)
  180. {
  181. colorA = A.GetPixels();
  182. }
  183. //通道选取
  184. for (int i = 0; i < imageWH.x * imageWH.y; i++)
  185. {
  186. //最终图像R通道 = TexR的选定Channel
  187. if (texR != null)
  188. {
  189. if (texRChannel == Channel.取R通道)
  190. {
  191. colorAllCombined[i].r = colorR[i].r;
  192. }
  193. if (texRChannel == Channel.取G通道)
  194. {
  195. colorAllCombined[i].r = colorR[i].g;
  196. }
  197. if (texRChannel == Channel.取B通道)
  198. {
  199. colorAllCombined[i].r = colorR[i].b;
  200. }
  201. if (texRChannel == Channel.取A通道)
  202. {
  203. colorAllCombined[i].r = colorR[i].a;
  204. }
  205. }else { colorAllCombined[i].r = 0.0f; }
  206. //最终图像G通道 = TexG的选定Channel
  207. if (texG != null)
  208. {
  209. if (texGChannel == Channel.取R通道)
  210. {
  211. colorAllCombined[i].g = colorG[i].r;
  212. }
  213. if (texGChannel == Channel.取G通道)
  214. {
  215. colorAllCombined[i].g = colorG[i].g;
  216. }
  217. if (texGChannel == Channel.取B通道)
  218. {
  219. colorAllCombined[i].g = colorG[i].b;
  220. }
  221. if (texGChannel == Channel.取A通道)
  222. {
  223. colorAllCombined[i].g = colorG[i].a;
  224. }
  225. }else { colorAllCombined[i].g = 0.0f; }
  226. //最终图像B通道 = TexB的选定Channel
  227. if (texB != null)
  228. {
  229. if (texBChannel == Channel.取R通道)
  230. {
  231. colorAllCombined[i].b = colorB[i].r;
  232. }
  233. if (texBChannel == Channel.取G通道)
  234. {
  235. colorAllCombined[i].b = colorB[i].g;
  236. }
  237. if (texBChannel == Channel.取B通道)
  238. {
  239. colorAllCombined[i].b = colorB[i].b;
  240. }
  241. if (texBChannel == Channel.取A通道)
  242. {
  243. colorAllCombined[i].b = colorB[i].a;
  244. }
  245. }else { colorAllCombined[i].b = 0.0f; }
  246. //最终图像A通道 = TexA的选定Channel
  247. if (texA != null)
  248. {
  249. if (texAChannel == Channel.取R通道)
  250. {
  251. colorAllCombined[i].a = colorA[i].r;
  252. }
  253. if (texAChannel == Channel.取G通道)
  254. {
  255. colorAllCombined[i].a = colorA[i].g;
  256. }
  257. if (texAChannel == Channel.取B通道)
  258. {
  259. colorAllCombined[i].a = colorA[i].b;
  260. }
  261. if (texAChannel == Channel.取A通道)
  262. {
  263. colorAllCombined[i].a = colorA[i].a;
  264. }
  265. }else { colorAllCombined[i].a = 0.0f; }
  266. }
  267. //是否为黑白图
  268. if (isBlackAndWhite)
  269. {
  270. if(GrayMode == RGB_To_Gray_Mode.平均值法)//①平均值法
  271. {
  272. Color[] temp = colorAllCombined;//每个像素颜色
  273. List<float> t = new List<float>();//创建List(用于暂时装载颜色值)
  274. for (int j = 0; j < temp.Length; j++)
  275. {
  276. t.Add(temp[j].r * 0.33334f + temp[j].g * 0.33334f + temp[j].b * 0.33334f);
  277. colorAllCombined[j].r = t[j];
  278. colorAllCombined[j].g = t[j];
  279. colorAllCombined[j].b = t[j];
  280. }
  281. }
  282. if(GrayMode == RGB_To_Gray_Mode.OpenCV彩色转灰度)//②OpenCV彩色图转灰度图
  283. {
  284. Color[] temp = colorAllCombined;
  285. List<float> t = new List<float>();
  286. for (int j = 0; j < temp.Length; j++)
  287. {
  288. //简化版(0.3,0.59,0.11)
  289. t.Add((temp[j].r * 0.299f + temp[j].g * 0.587f + temp[j].b * 0.114f));
  290. colorAllCombined[j].r = t[j];
  291. colorAllCombined[j].g = t[j];
  292. colorAllCombined[j].b = t[j];
  293. }
  294. }
  295. }
  296. //最终输出
  297. if (texR != null || texG != null || texB != null || texA != null)
  298. {
  299. texAllCombined.SetPixels(colorAllCombined);
  300. texAllCombined.Apply();
  301. if (mat != null)
  302. {
  303. mat.SetTexture(matTexName, texAllCombined);
  304. Debug.Log("贴图已同步赋予到材质 以查看效果");
  305. }
  306. Save(colorAllCombined);
  307. }
  308. }
  309. //-------------------非主要附加函数-----------------
  310. Texture2D ScaleTexture(Texture2D source, float targetWidth, float targetHeight)//缩放图像(经过双线性过滤)
  311. {
  312. Texture2D result = new Texture2D((int)targetWidth, (int)targetHeight, source.format, false);
  313. float incX = (1.0f / targetWidth);
  314. float incY = (1.0f / targetHeight);
  315. for (int i = 0; i < result.height; ++i)
  316. {
  317. for (int j = 0; j < result.width; ++j)
  318. {
  319. Color newColor = source.GetPixelBilinear((float)j / (float)result.width, (float)i / (float)result.height);
  320. result.SetPixel(j, i, newColor);
  321. }
  322. }
  323. result.Apply();
  324. return result;
  325. }
  326. [ContextMenu("选择保存路径")]
  327. void ChooseSavePath()
  328. {
  329. customPath = EditorUtility.OpenFolderPanel("", "", "");
  330. }
  331. }