GraphicData.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /**
  2. * 魔力宝贝图档解析脚本 - CGTool
  3. *
  4. * @Author HonorLee (dev@honorlee.me)
  5. * @Version 1.0 (2023-11-20)
  6. * @License GPL-3.0
  7. *
  8. * GraphicData.cs 图档解析类
  9. */
  10. using System;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using System.IO;
  14. using System.Linq;
  15. using Unity.Burst;
  16. using Unity.Collections;
  17. using Unity.Jobs;
  18. using UnityEngine;
  19. namespace CrossgateToolkit
  20. {
  21. //图档数据详情
  22. public class GraphicDetail
  23. {
  24. //索引
  25. public uint Index;
  26. //编号
  27. public uint Serial;
  28. //图档宽度
  29. public uint Width;
  30. //图档高度
  31. public uint Height;
  32. //图档偏移X
  33. public int OffsetX;
  34. //图档偏移Y
  35. public int OffsetY;
  36. //Palet调色板Index
  37. public int Palet;
  38. //图档Sprite
  39. public Sprite Sprite;
  40. //图档Sprite(100%PPU)
  41. public Sprite SpritePPU100;
  42. //图档主色调,用于小地图绘制
  43. public Color32 PrimaryColor;
  44. }
  45. // 图档数据
  46. public static class GraphicData
  47. {
  48. // 常规图档缓存
  49. public static Dictionary<GraphicInfoData,Dictionary<int,GraphicDetail>> _cache = new Dictionary<GraphicInfoData, Dictionary<int, GraphicDetail>>();
  50. // 线性图档缓存
  51. public static Dictionary<GraphicInfoData,Dictionary<int,GraphicDetail>> _linearCache = new Dictionary<GraphicInfoData, Dictionary<int, GraphicDetail>>();
  52. // 获取图档
  53. public static GraphicDetail GetGraphicDetail(GraphicInfoData graphicInfoData, int palet = 0,int subPalet = -1,bool asLinear = false,bool cache = true)
  54. {
  55. GraphicDetail graphicDetail = null;
  56. if (cache)
  57. {
  58. var checkCache = asLinear ? _linearCache : _cache;
  59. if (checkCache.ContainsKey(graphicInfoData))
  60. {
  61. if (checkCache[graphicInfoData].ContainsKey(palet))
  62. {
  63. graphicDetail = checkCache[graphicInfoData][palet];
  64. }
  65. else
  66. {
  67. graphicDetail = _loadGraphicDetail(graphicInfoData, palet, subPalet, asLinear);
  68. checkCache[graphicInfoData].Add(palet, graphicDetail);
  69. }
  70. }
  71. else
  72. {
  73. graphicDetail = _loadGraphicDetail(graphicInfoData, palet, subPalet, asLinear);
  74. checkCache.Add(graphicInfoData, new Dictionary<int, GraphicDetail>());
  75. checkCache[graphicInfoData].Add(palet, graphicDetail);
  76. }
  77. }
  78. else
  79. {
  80. graphicDetail = _loadGraphicDetail(graphicInfoData, palet, subPalet, asLinear);
  81. }
  82. return graphicDetail;
  83. }
  84. public static void ClearCache(uint serial,int palet =0,bool asLinear = false)
  85. {
  86. var checkCache = asLinear ? _linearCache : _cache;
  87. GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoData(serial);
  88. if (graphicInfoData == null) return;
  89. if (checkCache.ContainsKey(graphicInfoData))
  90. {
  91. if (checkCache[graphicInfoData].ContainsKey(palet))
  92. {
  93. GraphicDetail graphicDetail = checkCache[graphicInfoData][palet];
  94. if (graphicDetail != null)
  95. {
  96. UnityEngine.Object.Destroy(graphicDetail.Sprite.texture);
  97. if (graphicDetail.Sprite != null)
  98. {
  99. UnityEngine.Object.Destroy(graphicDetail.Sprite);
  100. UnityEngine.Object.Destroy(graphicDetail.SpritePPU100);
  101. }
  102. graphicDetail = null;
  103. }
  104. checkCache[graphicInfoData].Remove(palet);
  105. }
  106. }
  107. }
  108. // 解析图档
  109. private static GraphicDetail _loadGraphicDetail(GraphicInfoData graphicInfoData,int palet = 0,int subPalet = -1,bool asLinear = false)
  110. {
  111. GraphicDetail graphicDetail = new GraphicDetail();
  112. //获取图像数据
  113. List<Color32> pixels = UnpackGraphic(graphicInfoData, palet, subPalet);
  114. if(pixels==null) return null;
  115. graphicDetail.PrimaryColor = pixels.Last();
  116. pixels.RemoveAt(pixels.Count - 1);
  117. //直接通过Texture2D做偏移,并转为Sprite的偏移量
  118. Vector2 offset = new Vector2(0f, 1f);
  119. offset.x += -(graphicInfoData.OffsetX * 1f) / graphicInfoData.Width;
  120. offset.y -= (-graphicInfoData.OffsetY * 1f) / graphicInfoData.Height;
  121. //创建Texture2D对象
  122. Texture2D texture2D;
  123. Sprite sprite;
  124. // RGBA4444 减少内存占用-对边缘增加1px空白,避免黑线
  125. texture2D = new Texture2D((int) graphicInfoData.Width, (int) graphicInfoData.Height,
  126. TextureFormat.RGBA4444, false, asLinear);
  127. // 固定点过滤
  128. if (asLinear) texture2D.filterMode = FilterMode.Bilinear;
  129. else texture2D.filterMode = FilterMode.Point;
  130. texture2D.wrapMode = TextureWrapMode.Clamp;
  131. texture2D.SetPixels32(pixels.ToArray());
  132. texture2D.Apply();
  133. sprite = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), offset, 1,0,SpriteMeshType.FullRect);
  134. // 创建PPU为100的sprite
  135. Sprite spritePPU100 = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), offset, 100,0,SpriteMeshType.FullRect);
  136. //写入数据
  137. graphicDetail.Index = graphicInfoData.Index;
  138. graphicDetail.Serial = graphicInfoData.Serial;
  139. graphicDetail.Width = graphicInfoData.Width;
  140. graphicDetail.Height = graphicInfoData.Height;
  141. graphicDetail.OffsetX = graphicInfoData.OffsetX;
  142. graphicDetail.OffsetY = graphicInfoData.OffsetY;
  143. graphicDetail.Palet = palet;
  144. graphicDetail.Sprite = sprite;
  145. graphicDetail.SpritePPU100 = spritePPU100;
  146. return graphicDetail;
  147. }
  148. #region 地图合批
  149. // 合批数据
  150. private class BatchData
  151. {
  152. public int BatchOffsetX;
  153. public int BatchOffsetY;
  154. public GraphicInfoData GraphicInfoData;
  155. // public List<Color32> Pixels;
  156. public Color32 PrimaryColor;
  157. public GraphicDetail GraphicDetail;
  158. }
  159. // 图档合批
  160. private class TextureData
  161. {
  162. public int MaxHeight;
  163. public int MaxWidth;
  164. public List<BatchData> BatchDatas = new List<BatchData>();
  165. public List<GraphicInfoData> GraphicInfoDatas = new List<GraphicInfoData>();
  166. }
  167. /// <summary>
  168. /// 合批图档
  169. /// 通过指定图档序列,对图档进行合批处理,并返回合批后的图档数据
  170. /// </summary>
  171. /// <param name="graphicInfoDatas">图档索引数据序列</param>
  172. /// <param name="AsSerialBatch">以图档编号而非索引号返回合批数据</param>
  173. /// <param name="palet">调色板序号</param>
  174. /// <param name="subPalet">副调色板编号(针对动画)</param>
  175. /// <param name="linear">线性过滤</param>
  176. /// <param name="maxTextureSize">单个Texture最大尺寸,地面数据建议2048,物件数据建议4096</param>
  177. /// <param name="padding">图档间隔,可以有效避免图档渲染时出现多余的黑边或像素黏连</param>
  178. /// <param name="compress">启用压缩</param>
  179. /// <returns>合批后的图档数据,Key(unit)为图档数据编号(或AsSerialBatch为false时为图档序号),Value为图档数据</returns>
  180. public static Dictionary<uint, GraphicDetail> BakeGraphics(List<GraphicInfoData> graphicInfoDatas,bool AsSerialBatch = true,int palet = 0,int subPalet = -1,bool linear = false,int maxTextureSize = 2048,int padding = 0,bool compress = false)
  181. {
  182. // 单个Texture最大尺寸
  183. int maxWidth = maxTextureSize;
  184. int maxHeight = maxTextureSize;
  185. List<TextureData> textureDatas = new List<TextureData>();
  186. // 根据objectInfos的内,GraphicInfoData的Width,Height进行排序,优先排序Width,使图档从小到大排列
  187. graphicInfoDatas = graphicInfoDatas.OrderBy(obj => obj.Width).ThenBy(obj => obj.Height).ToList();
  188. // 去重
  189. graphicInfoDatas = graphicInfoDatas.Distinct().ToList();
  190. int offsetX = 0; // X轴偏移量
  191. int offsetY = 0; // Y轴偏移量
  192. int maxRowHeight = 0; // 当前行最大高度
  193. TextureData textureData = new TextureData();
  194. for (var i = 0; i < graphicInfoDatas.Count; i++)
  195. {
  196. GraphicInfoData graphicInfoData = graphicInfoDatas[i];
  197. // 如果宽度超过4096,则换行
  198. if((graphicInfoData.Width + offsetX) > maxWidth)
  199. {
  200. offsetX = 0;
  201. offsetY = offsetY + maxRowHeight + padding;
  202. maxRowHeight = 0;
  203. }
  204. // 如果高度超过2048,则生成新的Texture2D
  205. if ((graphicInfoData.Height + offsetY) > maxHeight)
  206. {
  207. offsetX = 0;
  208. offsetY = 0;
  209. maxRowHeight = 0;
  210. textureDatas.Add(textureData);
  211. textureData = new TextureData();
  212. }
  213. BatchData batchData = new BatchData();
  214. batchData.BatchOffsetX = offsetX;
  215. batchData.BatchOffsetY = offsetY;
  216. batchData.GraphicDetail = GetGraphicDetail(graphicInfoData, palet, subPalet, linear, true);
  217. batchData.GraphicInfoData = graphicInfoData;
  218. batchData.PrimaryColor = batchData.GraphicDetail.PrimaryColor;
  219. textureData.BatchDatas.Add(batchData);
  220. textureData.GraphicInfoDatas.Add(graphicInfoData);
  221. maxRowHeight = Mathf.Max(maxRowHeight, (int) graphicInfoData.Height);
  222. textureData.MaxHeight = Mathf.Max(textureData.MaxHeight, offsetY + maxRowHeight);
  223. textureData.MaxWidth = Mathf.Max(textureData.MaxWidth, offsetX + (int) graphicInfoData.Width);
  224. offsetX += (int) graphicInfoData.Width + padding;
  225. }
  226. //最后一次合并
  227. if (textureData.BatchDatas.Count > 0) textureDatas.Add(textureData);
  228. Dictionary<uint, GraphicDetail> graphicDataDic = new Dictionary<uint, GraphicDetail>();
  229. //合并Texture2D
  230. for (var i = 0; i < textureDatas.Count; i++)
  231. {
  232. TextureData textureDataPiece = textureDatas[i];
  233. // 将最大高宽调整为4的倍数,提高渲染效率及适配压缩
  234. textureDataPiece.MaxWidth = (int) Math.Ceiling(textureDataPiece.MaxWidth / 4f) * 4;
  235. textureDataPiece.MaxHeight = (int) Math.Ceiling(textureDataPiece.MaxHeight / 4f) * 4;
  236. // Debug.Log($"合并第{i}个Texture2D,最大高度:{textureDataPiece.MaxHeight},图像数量:{textureDataPiece.GraphicDatas.Count}");
  237. Color32[] colors = Enumerable.Repeat(new Color32(0,0,0,0), textureDataPiece.MaxWidth * textureDataPiece.MaxHeight).ToArray();
  238. Texture2D texture2DPiece = new Texture2D(textureDataPiece.MaxWidth, textureDataPiece.MaxHeight, TextureFormat.RGBA4444, false, linear);
  239. texture2DPiece.filterMode = linear ? FilterMode.Bilinear : FilterMode.Point;
  240. texture2DPiece.wrapMode = TextureWrapMode.Clamp;
  241. texture2DPiece.SetPixels32(colors);
  242. texture2DPiece.Apply();
  243. for (var n = 0; n < textureDataPiece.BatchDatas.Count; n++)
  244. {
  245. BatchData batchData = textureDataPiece.BatchDatas[n];
  246. GraphicInfoData graphicInfoData = textureDataPiece.GraphicInfoDatas[n];
  247. Graphics.CopyTexture(batchData.GraphicDetail.Sprite.texture, 0, 0, 0, 0, (int) graphicInfoData.Width,
  248. (int) graphicInfoData.Height, texture2DPiece, 0, 0, batchData.BatchOffsetX,
  249. batchData.BatchOffsetY);
  250. }
  251. Combine(texture2DPiece, textureDataPiece.BatchDatas);
  252. }
  253. void Combine(Texture2D texture2D,List<BatchData> batchDatas)
  254. {
  255. for (var i = 0; i < batchDatas.Count; i++)
  256. {
  257. BatchData batchData = batchDatas[i];
  258. //直接通过Texture2D做偏移,并转为Sprite的偏移量
  259. Vector2 offset = new Vector2(0f, 1f);
  260. offset.x += -(batchData.GraphicInfoData.OffsetX * 1f) / batchData.GraphicInfoData.Width;
  261. offset.y -= (-batchData.GraphicInfoData.OffsetY * 1f) / batchData.GraphicInfoData.Height;
  262. Sprite sprite = Sprite.Create(texture2D,
  263. new Rect(batchData.BatchOffsetX, batchData.BatchOffsetY, (int)batchData.GraphicInfoData.Width,
  264. (int)batchData.GraphicInfoData.Height), offset, 1, 0, SpriteMeshType.FullRect);
  265. Sprite spritePPU100 = Sprite.Create(texture2D,
  266. new Rect(batchData.BatchOffsetX, batchData.BatchOffsetY, (int)batchData.GraphicInfoData.Width,
  267. (int)batchData.GraphicInfoData.Height), offset, 100, 0, SpriteMeshType.FullRect);
  268. GraphicDetail graphicDetail = new GraphicDetail()
  269. {
  270. Index = batchData.GraphicInfoData.Index,
  271. Serial = batchData.GraphicInfoData.Serial,
  272. Width = batchData.GraphicInfoData.Width,
  273. Height = batchData.GraphicInfoData.Height,
  274. OffsetX = batchData.GraphicInfoData.OffsetX,
  275. OffsetY = batchData.GraphicInfoData.OffsetY,
  276. Palet = palet,
  277. Sprite = sprite,
  278. SpritePPU100 = spritePPU100,
  279. PrimaryColor = batchData.PrimaryColor
  280. };
  281. // graphicDataPiece.Sprite = sprite;
  282. if (AsSerialBatch) graphicDataDic[graphicDetail.Serial] = graphicDetail;
  283. else graphicDataDic[graphicDetail.Index] = graphicDetail;
  284. ClearCache(graphicDetail.Serial);
  285. if(compress) texture2D.Compress(true);
  286. }
  287. }
  288. return graphicDataDic;
  289. }
  290. #endregion
  291. //解压图像数据
  292. public static List<Color32> UnpackGraphic(GraphicInfoData graphicInfoData, int PaletIndex = 0,
  293. int SubPaletIndex = -1)
  294. {
  295. List<Color32> pixels = new List<Color32>();
  296. //获取调色板
  297. List<Color32> palet = null;
  298. //调整流指针
  299. BinaryReader fileReader = graphicInfoData.GraphicReader;
  300. fileReader.BaseStream.Position = graphicInfoData.Addr;
  301. //读入目标字节集
  302. byte[] Content = fileReader.ReadBytes((int)graphicInfoData.Length);
  303. //读取缓存字节集
  304. BinaryReader contentReader = new BinaryReader(new MemoryStream(Content));
  305. //16字节头信息
  306. byte[] RD = contentReader.ReadBytes(2);
  307. // 研究了几个图档数据,这个字节分别有 0~3 不同类型
  308. // 猜想一下的话
  309. // 0:图档无压缩无内置图档
  310. // 1:图档压缩无内置图档
  311. // 2:图档无压缩有内置图档
  312. // 3:图档压缩有内置图档
  313. int Version = contentReader.ReadByte();
  314. int Unknow = contentReader.ReadByte();
  315. uint Width = contentReader.ReadUInt32();
  316. uint Height = contentReader.ReadUInt32();
  317. uint DataLen = contentReader.ReadUInt32();
  318. uint innerPaletLen = 0;
  319. // 低版本头部长度为16,高版本为20
  320. int headLen = 16;
  321. if (Version > 1)
  322. {
  323. headLen = 20;
  324. innerPaletLen = contentReader.ReadUInt32();
  325. }
  326. //数据长度
  327. int contentLen = (int)(DataLen - headLen);
  328. int pixelLen = (int)(graphicInfoData.Width * graphicInfoData.Height);
  329. byte[] paletIndexs = graphicInfoData.UnpackedPaletIndex;
  330. if (paletIndexs == null)
  331. {
  332. //解压数据
  333. byte[] contentBytes =
  334. contentReader.ReadBytes((int)Version % 2 == 0 ? (int)(pixelLen + innerPaletLen) : contentLen);
  335. NativeArray<byte> bytes = new NativeArray<byte>((int)contentBytes.Length, Allocator.TempJob);
  336. bytes.CopyFrom(contentBytes);
  337. long decompressLen = pixelLen + innerPaletLen;
  338. NativeArray<byte> colorIndexs =
  339. new NativeArray<byte>((int)decompressLen, Allocator.TempJob);
  340. DecompressJob decompressJob = new DecompressJob()
  341. {
  342. bytes = bytes,
  343. compressd = Version % 2 != 0,
  344. colorIndexs = colorIndexs
  345. };
  346. // decompressJob.Execute();
  347. decompressJob.Schedule().Complete();
  348. paletIndexs = colorIndexs.ToArray();
  349. graphicInfoData.UnpackedPaletIndex = paletIndexs;
  350. // 如果存在内置调色板,则读取内置调色板
  351. if (innerPaletLen > 0 && graphicInfoData.InnerPalet == null)
  352. {
  353. byte[] innerPaletIndex = paletIndexs.Skip(pixelLen).Take((int)innerPaletLen).ToArray();
  354. graphicInfoData.InnerPalet = AnalysisInnerPalet(innerPaletIndex).ToList();
  355. }
  356. bytes.Dispose();
  357. colorIndexs.Dispose();
  358. }
  359. paletIndexs = paletIndexs.Take(pixelLen).ToArray();
  360. // palet = Palet.GetPalet(PaletIndex);
  361. // Debug.Log($"PaletIndex:{PaletIndex},SubPaletIndex:{SubPaletIndex},palet:{palet!=null},InnerPalet:{graphicInfoData.InnerPalet!=null}");
  362. // 如果指定了外置调色板
  363. if (SubPaletIndex >= 0)
  364. {
  365. palet = Palet.GetPalet(SubPaletIndex);
  366. if (palet == null)
  367. {
  368. GraphicInfoData subPaletInfoData = GraphicInfo.GetGraphicInfoData((uint)SubPaletIndex);
  369. if (subPaletInfoData != null)
  370. {
  371. Graphic.GetGraphicDetail((uint)SubPaletIndex);
  372. if (subPaletInfoData.InnerPalet != null)
  373. {
  374. palet = subPaletInfoData.InnerPalet;
  375. Palet.AddPalet(SubPaletIndex, palet);
  376. }
  377. }
  378. }
  379. }
  380. if (palet == null)
  381. {
  382. if (graphicInfoData.InnerPalet != null)
  383. {
  384. // 没有指定外置调色板,存在内置调色板,则读取内置调色板
  385. palet = graphicInfoData.InnerPalet;
  386. }
  387. else
  388. {
  389. palet = Palet.GetPalet(PaletIndex);
  390. if (palet == null) palet = Palet.GetPalet(0);
  391. }
  392. }
  393. //释放连接
  394. contentReader.Dispose();
  395. contentReader.Close();
  396. //主色调色值
  397. int r = 0;
  398. int g = 0;
  399. int b = 0;
  400. foreach (int index in paletIndexs)
  401. {
  402. Color32 color32;
  403. if (index == 0 || (index > palet.Count - 1))
  404. {
  405. color32 = Color.clear;
  406. }
  407. else
  408. {
  409. color32 = palet[index];
  410. }
  411. pixels.Add(color32);
  412. r += color32.r;
  413. g += color32.g;
  414. b += color32.b;
  415. }
  416. //主色调计算及提亮
  417. r = r / pixels.Count * 3;
  418. g = g / pixels.Count * 3;
  419. b = b / pixels.Count * 3;
  420. if (r > 255) r = 255;
  421. if (g > 255) g = 255;
  422. if (b > 255) b = 255;
  423. int len = (int) (graphicInfoData.Width * graphicInfoData.Height);
  424. if (pixels.Count != len)
  425. {
  426. if (pixels.Count > len)
  427. {
  428. pixels = pixels.GetRange(0, len);
  429. }
  430. else
  431. {
  432. Color32[] temc = new Color32[len - pixels.Count];
  433. ArrayList.Repeat(Color.clear, len - pixels.Count).CopyTo(temc);
  434. pixels.AddRange(temc);
  435. }
  436. }
  437. //主色调加入最后
  438. pixels.Add(new Color32((byte) r, (byte) g, (byte) b, 255));
  439. return pixels;
  440. }
  441. //分析高版本内部调色板
  442. private static Color32[] AnalysisInnerPalet(byte[] bytes)
  443. {
  444. int colorLen = bytes.Length / 3;
  445. Color32[] palet = new Color32[colorLen + 1];
  446. for (var i = 0; i < colorLen; i++)
  447. {
  448. byte[] paletBytes = bytes.Skip(i * 3).Take(3).ToArray();
  449. Color32 color32 = new Color32();
  450. color32.r = (byte)paletBytes[2];
  451. color32.g = (byte)paletBytes[1];
  452. color32.b = (byte)paletBytes[0];
  453. color32.a = (byte)(i == 0 ? 0x00 : 0xFF);
  454. palet[i] = color32;
  455. }
  456. palet[colorLen] = Color.clear;
  457. return palet;
  458. }
  459. #region 测试解压
  460. private static int[] TestDecompress(byte[] bytes)
  461. {
  462. List<int> colorIndexs = new List<int>();
  463. int _index = -1;
  464. int next()
  465. {
  466. _index++;
  467. if (_index > bytes.Length - 1) return -1;
  468. return bytes[_index];
  469. }
  470. while (_index < (bytes.Length - 1))
  471. {
  472. int head = next();
  473. if (head == -1) break;
  474. int repeat = 0;
  475. if (head < 0x10)
  476. {
  477. repeat = head;
  478. for (var i = 0; i < repeat; i++)
  479. {
  480. colorIndexs.Add(next());
  481. }
  482. }
  483. else if (head < 0x20)
  484. {
  485. repeat = head % 0x10 * 0x100 + next();
  486. for (var i = 0; i < repeat; i++)
  487. {
  488. colorIndexs.Add(next());
  489. }
  490. }
  491. else if (head < 0x80)
  492. {
  493. repeat = head % 0x20 * 0x10000 + next() * 0x100 + next();
  494. for (var i = 0; i < repeat; i++)
  495. {
  496. colorIndexs.Add(next());
  497. }
  498. }
  499. else if (head < 0x90)
  500. {
  501. repeat = head % 0x80;
  502. int index = next();
  503. for (var i = 0; i < repeat; i++)
  504. {
  505. colorIndexs.Add(index);
  506. }
  507. }
  508. else if (head < 0xa0)
  509. {
  510. int index = next();
  511. repeat = head % 0x90 * 0x100 + next();
  512. for (var i = 0; i < repeat; i++)
  513. {
  514. colorIndexs.Add(index);
  515. }
  516. }
  517. else if (head < 0xc0)
  518. {
  519. int index = next();
  520. repeat = head % 0xa0 * 0x10000 + next() * 0x100 + next();
  521. for (var i = 0; i < repeat; i++)
  522. {
  523. colorIndexs.Add(index);
  524. }
  525. }
  526. else if (head < 0xd0)
  527. {
  528. repeat = head % 0xc0;
  529. for (var i = 0; i < repeat; i++)
  530. {
  531. colorIndexs.Add(0);
  532. }
  533. }
  534. else if (head < 0xe0)
  535. {
  536. repeat = head % 0xd0 * 0x100 + next();
  537. for (var i = 0; i < repeat; i++)
  538. {
  539. colorIndexs.Add(0);
  540. }
  541. }
  542. else if (head < 0xff)
  543. {
  544. repeat = head % 0xe0 * 0x10000 + next() * 0x100 + next();
  545. for (var i = 0; i < repeat; i++)
  546. {
  547. colorIndexs.Add(0);
  548. }
  549. }
  550. }
  551. return colorIndexs.ToArray();
  552. }
  553. #endregion 测试解压
  554. }
  555. //解压缩交给IJob处理
  556. [BurstCompile]
  557. public struct DecompressJob : IJob
  558. {
  559. [ReadOnly]
  560. public NativeArray<byte> bytes;
  561. public bool compressd;
  562. public NativeArray<byte> colorIndexs;
  563. private int _maxIndex;
  564. private int _index;
  565. private int _colorIndex;
  566. private int NextByte()
  567. {
  568. _index++;
  569. if (_index > _maxIndex) return -1;
  570. return bytes[_index];
  571. }
  572. private void AddColorIndex(byte index)
  573. {
  574. if (_colorIndex > colorIndexs.Length - 1) return;
  575. colorIndexs[_colorIndex] = index;
  576. _colorIndex++;
  577. }
  578. [BurstCompile]
  579. public void Execute()
  580. {
  581. _maxIndex = bytes.Length - 1;
  582. _index = -1;
  583. _colorIndex = 0;
  584. if (!compressd)
  585. {
  586. while (_index<=_maxIndex)
  587. {
  588. int pindex = NextByte();
  589. if(pindex==-1) break;
  590. AddColorIndex((byte)pindex);
  591. }
  592. }
  593. else
  594. //压缩型数据解压
  595. {
  596. // int count = 0;
  597. while (_index<=_maxIndex)
  598. {
  599. // count++;
  600. int head = NextByte();
  601. if(head==-1) break;
  602. int repeat = 0;
  603. if (head < 0x10)
  604. {
  605. repeat = head;
  606. for (var i = 0; i < repeat; i++)
  607. {
  608. AddColorIndex((byte)NextByte());
  609. }
  610. }
  611. else if (head < 0x20)
  612. {
  613. repeat = head % 0x10 * 0x100 + NextByte();
  614. for (var i = 0; i < repeat; i++)
  615. {
  616. AddColorIndex((byte)NextByte());
  617. }
  618. }
  619. else if (head < 0x80)
  620. {
  621. repeat = head % 0x20 * 0x10000 + NextByte() * 0x100 + NextByte();
  622. for (var i = 0; i < repeat; i++)
  623. {
  624. AddColorIndex((byte)NextByte());
  625. }
  626. }
  627. else if (head < 0x90)
  628. {
  629. repeat = head % 0x80;
  630. byte index = (byte)NextByte();
  631. for (var i = 0; i < repeat; i++)
  632. {
  633. AddColorIndex(index);
  634. }
  635. }
  636. else if (head < 0xa0)
  637. {
  638. byte index = (byte)NextByte();
  639. repeat = head % 0x90 * 0x100 + NextByte();
  640. for (var i = 0; i < repeat; i++)
  641. {
  642. AddColorIndex(index);
  643. }
  644. }
  645. else if (head < 0xc0)
  646. {
  647. byte index = (byte)NextByte();
  648. repeat = head % 0xa0 * 0x10000 + NextByte() * 0x100 + NextByte();
  649. for (var i = 0; i < repeat; i++)
  650. {
  651. AddColorIndex(index);
  652. }
  653. }
  654. else if (head < 0xd0)
  655. {
  656. repeat = head % 0xc0;
  657. for (var i = 0; i < repeat; i++)
  658. {
  659. AddColorIndex(0);
  660. }
  661. }
  662. else if (head < 0xe0)
  663. {
  664. repeat = head % 0xd0 * 0x100 + NextByte();
  665. for (var i = 0; i < repeat; i++)
  666. {
  667. AddColorIndex(0);
  668. }
  669. }
  670. else
  671. {
  672. repeat = head % 0xe0 * 0x10000 + NextByte() * 0x100 + NextByte();
  673. for (var i = 0; i < repeat; i++)
  674. {
  675. AddColorIndex(0);
  676. }
  677. }
  678. }
  679. }
  680. }
  681. }
  682. }