PageRenderTime 52ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/AtlasBuilder.cs

https://bitbucket.org/rstarkov/tankiconmaker
C# | 239 lines | 222 code | 17 blank | 0 comment | 31 complexity | 29cbb633ca21537b68291945dca9dae2 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-3.0, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows.Media.Imaging;
  9. using System.Xml.Linq;
  10. using RT.Util.Dialogs;
  11. using WotDataLib;
  12. namespace TankIconMaker
  13. {
  14. class AtlasBuilder
  15. {
  16. private WotContext context;
  17. public AtlasBuilder(WotContext CurContext)
  18. {
  19. context = CurContext;
  20. }
  21. private struct SubTextureStruct
  22. {
  23. public string FName;
  24. public System.Drawing.Bitmap ImageTank;
  25. public System.Drawing.Rectangle LocRect;
  26. public int MaxParty;
  27. public SubTextureStruct(string FName, System.Drawing.Bitmap ImageTank, System.Drawing.Rectangle LocRect, int MaxParty)
  28. {
  29. this.FName = FName;
  30. this.ImageTank = ImageTank;
  31. this.LocRect = LocRect;
  32. this.MaxParty = MaxParty;
  33. }
  34. }
  35. private void CreateAtlasXML(ref List<SubTextureStruct> ImageList, string filename)
  36. {
  37. FileStream fileXML = new FileStream(filename, FileMode.Create);
  38. StreamWriter writer = new StreamWriter(fileXML);
  39. writer.WriteLine("<root>");
  40. foreach (var SubTexture in ImageList)
  41. {
  42. writer.WriteLine(" <SubTexture>");
  43. writer.WriteLine(" <name> " + SubTexture.FName + " </name>");
  44. writer.WriteLine(" <x> " + (int)SubTexture.LocRect.X + " </x>");
  45. writer.WriteLine(" <y> " + (int)SubTexture.LocRect.Y + " </y>");
  46. writer.WriteLine(" <width> " + (int)SubTexture.LocRect.Width + " </width>");
  47. writer.WriteLine(" <height> " + (int)SubTexture.LocRect.Height + " </height>");
  48. writer.WriteLine(" </SubTexture>");
  49. }
  50. writer.Write("</root>");
  51. writer.Close();
  52. }
  53. private void CreateAtlasPNG(ref List<SubTextureStruct> ImageList, string filename)
  54. {
  55. System.Drawing.Bitmap AtlasPNG = new System.Drawing.Bitmap(2048, 2048);
  56. AtlasPNG.SetResolution(96.0F, 96.0F);
  57. for (int i = 0; i < ImageList.Count; i++)
  58. {
  59. System.Drawing.Bitmap PNG = ImageList[i].ImageTank;
  60. using (System.Drawing.Graphics gPNG = System.Drawing.Graphics.FromImage(AtlasPNG))
  61. {
  62. gPNG.DrawImage(PNG, (int)ImageList[i].LocRect.X, (int)ImageList[i].LocRect.Y);
  63. }
  64. }
  65. AtlasPNG.Save(filename);
  66. }
  67. private void RadixSort(ref List<SubTextureStruct> ImageList)
  68. {
  69. int CInd;
  70. int[] C = new int[10];
  71. List<SubTextureStruct> ImageListTemp = new List<SubTextureStruct>(ImageList);
  72. int t = 1;
  73. for (int i = 1; i <= 4; i++)
  74. {
  75. for (int j = 0; j < 10; j++)
  76. C[j] = 0;
  77. for (int j = 0; j < ImageList.Count; j++)
  78. {
  79. CInd = (ImageList[j].MaxParty % (t * 10)) / t;
  80. C[CInd] = C[CInd] + 1;
  81. }
  82. for (int j = 8; j >= 0; j--)
  83. C[j] = C[j + 1] + C[j];
  84. for (int j = ImageList.Count - 1; j >= 0; j--)
  85. {
  86. CInd = (ImageList[j].MaxParty % (t * 10)) / t;
  87. ImageListTemp[C[CInd] - 1] = ImageList[j];
  88. C[CInd] = C[CInd] - 1;
  89. }
  90. t *= 10;
  91. ImageList = new List<SubTextureStruct>(ImageListTemp);
  92. }
  93. }
  94. private void Arrangement(ref List<SubTextureStruct> ImageList)
  95. {
  96. List<System.Drawing.Rectangle> TakePlaceList = new List<System.Drawing.Rectangle>();
  97. SubTextureStruct SubTexture;
  98. System.Drawing.Rectangle Rct, TakeRct;
  99. const int TextureHeight = 2048, TextureWidth = 2048;
  100. int CurrentY, j, k;
  101. TakePlaceList.Add(ImageList[0].LocRect);
  102. for (int i = 1; i < ImageList.Count; i++)
  103. {
  104. SubTexture = ImageList[i];
  105. Rct = SubTexture.LocRect;
  106. CurrentY = TextureHeight;
  107. j = 0;
  108. while (j < TakePlaceList.Count)
  109. if (TakePlaceList[j].IntersectsWith(Rct))
  110. {
  111. Rct.Location = new System.Drawing.Point(TakePlaceList[j].Right + 1, Rct.Y);
  112. if (TakePlaceList[j].Bottom > Rct.Y)
  113. CurrentY = Math.Min(CurrentY, TakePlaceList[j].Bottom - Rct.Y + 1);
  114. if (Rct.Right > TextureWidth)
  115. {
  116. Rct.Location = new System.Drawing.Point(0, Rct.Y + CurrentY);
  117. CurrentY = TextureHeight;
  118. }
  119. j = TakePlaceList.Count - 1;
  120. while ((j > 0) && (TakePlaceList[j].Bottom > Rct.Y))
  121. j--;
  122. }
  123. else
  124. j++;
  125. if (Rct.Bottom > TextureHeight)
  126. return; //необходимо обработать данную ситуацию
  127. j = TakePlaceList.Count - 1;
  128. while ((j >= 0) && (TakePlaceList[j].Bottom > Rct.Bottom))
  129. j--;
  130. k = j;
  131. while ((k >= 0) && (TakePlaceList[k].Bottom == Rct.Bottom))
  132. if ((Rct.X == TakePlaceList[k].Right + 1) && (Rct.Y == TakePlaceList[k].Y))
  133. {
  134. TakeRct = TakePlaceList[k];
  135. TakeRct.Width += Rct.Width + 1;
  136. TakePlaceList[k] = TakeRct;
  137. k = -1;
  138. j = -2;
  139. }
  140. else
  141. k--;
  142. if (j > -2)
  143. {
  144. j++;
  145. TakePlaceList.Insert(j, Rct);
  146. }
  147. SubTexture.LocRect = Rct;
  148. ImageList[i] = SubTexture;
  149. }
  150. }
  151. private void CreateImageList(ref List<SubTextureStruct> ImageList, WotContext context, string nameAtlas)
  152. {
  153. int X, Y, Width, Height, i;
  154. int BeginCount = ImageList.Count;
  155. Stream StreamAtlasPNG = ZipCache.GetZipFileStream(new CompositePath(context, context.Installation.Path, context.VersionConfig.PathSourceAtlas, nameAtlas + ".png"));
  156. System.Drawing.Bitmap AtlasPNG = new System.Drawing.Bitmap(StreamAtlasPNG);
  157. AtlasPNG.SetResolution(96.0F, 96.0F);
  158. Stream StreamAtlasXML = ZipCache.GetZipFileStream(new CompositePath(context, context.Installation.Path, context.VersionConfig.PathSourceAtlas, nameAtlas + ".xml"));
  159. XDocument AtlasXML = XDocument.Load(StreamAtlasXML);
  160. XElement Root = AtlasXML.Element("root");
  161. SubTextureStruct SubTextureTemp = new SubTextureStruct();
  162. foreach (XElement element in Root.Elements())
  163. {
  164. SubTextureTemp.FName = element.Element("name").Value.Trim();
  165. i = 0;
  166. while ((i < BeginCount) && (SubTextureTemp.FName != ImageList[i].FName))
  167. i++;
  168. if (i >= BeginCount)
  169. {
  170. X = Convert.ToInt32(element.Element("x").Value.Trim());
  171. Y = Convert.ToInt32(element.Element("y").Value.Trim());
  172. Width = Convert.ToInt32(element.Element("width").Value.Trim());
  173. Height = Convert.ToInt32(element.Element("height").Value.Trim());
  174. SubTextureTemp.ImageTank = new System.Drawing.Bitmap(Width, Height);
  175. SubTextureTemp.ImageTank.SetResolution(96.0F, 96.0F);
  176. SubTextureTemp.MaxParty = Math.Max(Width, Height);
  177. using (System.Drawing.Graphics gPNG = System.Drawing.Graphics.FromImage(SubTextureTemp.ImageTank))
  178. {
  179. gPNG.DrawImage(AtlasPNG, 0, 0, new System.Drawing.Rectangle(X, Y, Width, Height), System.Drawing.GraphicsUnit.Pixel);
  180. }
  181. SubTextureTemp.LocRect = new System.Drawing.Rectangle(0, 0, Width, Height);
  182. ImageList.Add(SubTextureTemp);
  183. }
  184. }
  185. }
  186. public void SaveAtlas(string pathTemplate, string atlasName, IEnumerable<RenderTask> renderTasks, bool custom = false)
  187. {
  188. List<SubTextureStruct> ImageList = new List<SubTextureStruct>();
  189. SubTextureStruct SubTexture = new SubTextureStruct();
  190. foreach (var render in renderTasks)
  191. {
  192. SubTexture.FName = render.TankId;
  193. using (MemoryStream outStream = new MemoryStream())
  194. {
  195. PngBitmapEncoder encoder = new PngBitmapEncoder();
  196. encoder.Frames.Add(BitmapFrame.Create(render.Image));
  197. encoder.Save(outStream);
  198. SubTexture.ImageTank = new System.Drawing.Bitmap(outStream);
  199. }
  200. SubTexture.LocRect = new System.Drawing.Rectangle(0, 0, render.Image.PixelWidth,
  201. render.Image.PixelHeight);
  202. if (!custom)
  203. {
  204. SubTexture.MaxParty = Math.Max(render.Image.PixelWidth, render.Image.PixelHeight);
  205. }
  206. ImageList.Add(SubTexture);
  207. }
  208. if (!custom)
  209. {
  210. this.CreateImageList(ref ImageList, context, atlasName);
  211. this.RadixSort(ref ImageList);
  212. }
  213. this.Arrangement(ref ImageList);
  214. if (!Directory.Exists(pathTemplate))
  215. {
  216. Directory.CreateDirectory(pathTemplate);
  217. }
  218. this.CreateAtlasPNG(ref ImageList, Path.Combine(pathTemplate, atlasName + ".png"));
  219. this.CreateAtlasXML(ref ImageList, Path.Combine(pathTemplate, atlasName + ".xml"));
  220. }
  221. }
  222. }