GraphicData.cs 25 KB

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