WeMadeLibrary.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.IO;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace LibraryEditor
  9. {
  10. public class WeMadeLibrary
  11. {
  12. private const string WixExtention = ".Wix",
  13. WilExtention = ".Wil",
  14. WzlExtention = ".Wzl",
  15. WzxExtention = ".Wzx",
  16. MizExtention = ".Miz",
  17. MixExtention = ".Mix",
  18. LibExtention = ".Lib";
  19. public WeMadeImage[] Images;
  20. private readonly string _fileName;
  21. private int[] _palette;
  22. private List<int> _indexList;
  23. private int _version = 0;
  24. private BinaryReader _bReader;
  25. private FileStream _fStream;
  26. private string _MainExtention = WilExtention;
  27. private string _IndexExtention = WixExtention;
  28. private bool _initialized;
  29. public byte _nType = 0; //0 = .wil //1 = .wzl //2 = .wil new wemade design //3 = .wil mir3 //4 = .miz shanda mir3 // 5 = 32bit wil
  30. private byte[] ImageStructureSize = { 8, 16, 16, 17, 16, 16 };//base size of an image structure
  31. public WeMadeLibrary(string name)
  32. {
  33. switch (Path.GetExtension(name).ToLower())
  34. {
  35. case ".wzl":
  36. _nType = 1;
  37. _MainExtention = WzlExtention;
  38. _IndexExtention = WzxExtention;
  39. break;
  40. case ".miz":
  41. _nType = 4;
  42. _MainExtention = MizExtention;
  43. _IndexExtention = MixExtention;
  44. break;
  45. }
  46. _fileName = Path.ChangeExtension(name, null);
  47. Initialize();
  48. }
  49. public void Initialize()
  50. {
  51. _initialized = true;
  52. if (!File.Exists(_fileName + _IndexExtention)) return;
  53. if (!File.Exists(_fileName + _MainExtention)) return;
  54. _fStream = new FileStream(_fileName + _MainExtention, FileMode.Open, FileAccess.Read);
  55. _bReader = new BinaryReader(_fStream);
  56. LoadImageInfo();
  57. for (int i = 0; i < Images.Length; i++)
  58. CheckImage(i);
  59. }
  60. private void LoadImageInfo()
  61. {
  62. byte[] buffer;
  63. _palette = new int[256] { -16777216, -8388608, -16744448, -8355840, -16777088, -8388480, -16744320, -4144960, -11173737, -6440504, -8686733, -13817559, -10857902, -10266022, -12437191, -14870504, -15200240, -14084072, -15726584, -886415, -2005153, -42406, -52943, -2729390, -7073792, -7067368, -13039616, -9236480, -4909056, -4365486, -12445680, -21863, -10874880, -9225943, -5944783, -7046285, -4369871, -11394800, -8703720, -13821936, -7583183, -7067392, -4378368, -3771566, -9752296, -3773630, -3257856, -5938375, -10866408, -14020608, -15398912, -12969984, -16252928, -14090240, -11927552, -6488064, -2359296, -2228224, -327680, -6524078, -7050422, -9221591, -11390696, -7583208, -7846895, -11919104, -14608368, -2714534, -3773663, -1086720, -35072, -5925756, -12439263, -15200248, -14084088, -14610432, -13031144, -7576775, -12441328, -9747944, -8697320, -7058944, -7568261, -9739430, -11910599, -14081768, -12175063, -4872812, -8688806, -3231340, -5927821, -7572646, -4877197, -2710157, -1071798, -1063284, -8690878, -9742791, -4352934, -10274560, -2701651, -11386327, -7052520, -1059155, -5927837, -10266038, -4348549, -10862056, -4355023, -13291223, -7043997, -8688822, -5927846, -10859991, -6522055, -12439280, -1069791, -15200256, -14081792, -6526208, -7044006, -11386344, -9741783, -8690911, -6522079, -2185984, -10857927, -13555440, -3228293, -10266055, -7044022, -3758807, -15688680, -12415926, -13530046, -15690711, -16246768, -16246760, -16242416, -15187415, -5917267, -9735309, -15193815, -15187382, -13548982, -10238242, -12263937, -7547153, -9213127, -532935, -528500, -530688, -9737382, -10842971, -12995089, -11887410, -13531979, -13544853, -2171178, -4342347, -7566204, -526370, -16775144, -16246727, -16248791, -16246784, -16242432, -16756059, -16745506, -15718070, -15713941, -15707508, -14591323, -15716006, -15711612, -13544828, -15195855, -11904389, -11375707, -14075549, -15709474, -14079711, -11908551, -14079720, -11908567, -8684734, -6513590, -10855895, -12434924, -13027072, -10921728, -3525332, -9735391, -14077696, -13551344, -13551336, -12432896, -11377896, -10849495, -13546984, -15195904, -15191808, -15189744, -10255286, -9716406, -10242742, -10240694, -10838966, -11891655, -10238390, -10234294, -11369398, -13536471, -10238374, -11354806, -15663360, -15193832, -11892662, -11868342, -16754176, -16742400, -16739328, -16720384, -16716288, -16712960, -11904364, -10259531, -8680234, -9733162, -8943361, -3750194, -7039844, -6515514, -13553351, -14083964, -15204220, -11910574, -11386245, -10265997, -3230217, -7570532, -8969524, -2249985, -1002454, -2162529, -1894477, -1040, -6250332, -8355712, -65536, -16711936, -256, -16776961, -65281, -16711681, -1, };
  64. if (_nType == 0) //at least we know it's a .wil file up to now
  65. {
  66. _fStream.Seek(0, SeekOrigin.Begin);
  67. buffer = _bReader.ReadBytes(49);
  68. if (buffer[40] == 1 || buffer[40] == 6)
  69. _nType = 2;
  70. else if (buffer[2] == 73 || buffer[2] == 72)
  71. _nType = 3;
  72. else if (buffer[48] == 32)
  73. {
  74. _nType = 5;
  75. }
  76. if ((_nType == 2 || _nType == 0) && _bReader.ReadInt16() == 32)
  77. {
  78. _nType = 5;
  79. }
  80. if (_nType == 0)
  81. {
  82. _fStream.Seek(48, SeekOrigin.Begin);
  83. _palette = new int[_bReader.ReadInt32()];
  84. _fStream.Seek(4, SeekOrigin.Current);
  85. _version = _bReader.ReadInt32();
  86. _fStream.Seek(_version == 0 ? 0 : 4, SeekOrigin.Current);
  87. for (int i = 1; i < _palette.Length; i++)
  88. _palette[i] = _bReader.ReadInt32() + (255 << 24);
  89. }
  90. }
  91. LoadIndexFile();
  92. Images = new WeMadeImage[_indexList.Count];
  93. }
  94. private void LoadIndexFile()
  95. {
  96. _indexList = new List<int>();
  97. FileStream stream = null;
  98. try
  99. {
  100. stream = new FileStream(_fileName + _IndexExtention, FileMode.Open, FileAccess.Read);
  101. stream.Seek(0, SeekOrigin.Begin);
  102. using (BinaryReader reader = new BinaryReader(stream))
  103. {
  104. switch (_nType)
  105. {
  106. case 4:
  107. stream.Seek(24, SeekOrigin.Begin);
  108. break;
  109. case 3:
  110. reader.ReadBytes(26);
  111. if (reader.ReadUInt16() != 0xB13A)
  112. stream.Seek(24, SeekOrigin.Begin);
  113. break;
  114. case 2:
  115. case 5:
  116. reader.ReadBytes(52);
  117. break;
  118. default:
  119. reader.ReadBytes(_version == 0 ? 48 : 52);
  120. break;
  121. }
  122. stream = null;
  123. while (reader.BaseStream.Position <= reader.BaseStream.Length - 4)
  124. _indexList.Add(reader.ReadInt32());
  125. }
  126. }
  127. finally
  128. {
  129. if (stream != null)
  130. stream.Dispose();
  131. }
  132. }
  133. private void CheckImage(int index)
  134. {
  135. if (!_initialized) Initialize();
  136. if (Images == null || index < 0 || index >= Images.Length) return;
  137. if (Images[index] == null)
  138. {
  139. _fStream.Position = _indexList[index];
  140. Images[index] = new WeMadeImage(_bReader, _nType);
  141. }
  142. if (Images[index].Image == null)
  143. {
  144. _fStream.Seek(_indexList[index] + (_nType > 0 ? ImageStructureSize[_nType] : _version == 0 ? 8 : 12), SeekOrigin.Begin);
  145. Images[index].CreateTexture(_bReader, _palette);
  146. }
  147. }
  148. public void ToMLibrary()
  149. {
  150. string fileName = Path.ChangeExtension(_fileName, ".Lib");
  151. if (File.Exists(fileName))
  152. File.Delete(fileName);
  153. MLibraryV2 library = new MLibraryV2(fileName) { Images = new List<MLibraryV2.MImage>(), IndexList = new List<int>(), Count = Images.Length };
  154. //library.Save();
  155. for (int i = 0; i < library.Count; i++)
  156. library.Images.Add(null);
  157. ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 8 };
  158. try
  159. {
  160. Parallel.For(0, Images.Length, options, i =>
  161. {
  162. WeMadeImage image = Images[i];
  163. if (image.HasMask)
  164. library.Images[i] = new MLibraryV2.MImage(image.Image, image.MaskImage) { X = image.X, Y = image.Y, ShadowX = image.ShadowX, ShadowY = image.ShadowY, Shadow = image.boHasShadow ? (byte)1 : (byte)0, MaskX = image.X, MaskY = image.Y };
  165. else
  166. library.Images[i] = new MLibraryV2.MImage(image.Image) { X = image.X, Y = image.Y, ShadowX = image.ShadowX, ShadowY = image.ShadowY, Shadow = image.boHasShadow ? (byte)1 : (byte)0 };
  167. });
  168. }
  169. catch (System.Exception)
  170. {
  171. throw;
  172. }
  173. finally
  174. {
  175. library.Save();
  176. }
  177. }
  178. public class WeMadeImage
  179. {
  180. public readonly short Width, Height, X, Y, ShadowX, ShadowY;
  181. public Rectangle TrueSize;
  182. public Bitmap Image;
  183. public long CleanTime;
  184. public byte nType = 0;
  185. public bool bo16bit = false;
  186. public int nSize;
  187. public bool boHasShadow;
  188. public bool HasMask;
  189. public Bitmap MaskImage;
  190. private int convert16bitTo32bit(int color)
  191. {
  192. byte red = (byte)((color & 0xf800) >> 8);
  193. byte green = (byte)((color & 0x07e0) >> 3);
  194. byte blue = (byte)((color & 0x001f) << 3);
  195. return ((red << 0x10) | (green << 0x8) | blue) | (255 << 24);//the final or is setting alpha to max so it'll display (since mir2 images have no alpha layer)
  196. }
  197. private int WidthBytes(int nBit, int nWidth)
  198. {
  199. return (((nWidth * nBit) + 31) >> 5) * 4;
  200. }
  201. private byte[][] DecompressWemadeMir3(BinaryReader BReader, short OutputWidth, short OutputHeight, int InputLength)
  202. {
  203. byte[][] Pixels = new byte[2][];
  204. Pixels[0] = new byte[OutputWidth * OutputHeight * 2];
  205. Pixels[1] = new byte[OutputWidth * OutputHeight * 2];
  206. int n = BReader.ReadInt32();
  207. if (n != 0) BReader.BaseStream.Seek(-4, SeekOrigin.Current);
  208. byte[] FileBytes = BReader.ReadBytes(InputLength * 2);
  209. int End = 0, OffSet = 0, Start = 0, Count;
  210. int nX, x = 0;
  211. //for (int Y = 0; Y < OutputHeight; Y++)
  212. for (int Y = OutputHeight - 1; Y >= 0; Y--)
  213. {
  214. OffSet = Start * 2;
  215. End += FileBytes[OffSet+1] << 8 | FileBytes[OffSet];
  216. Start++;
  217. nX = Start;
  218. OffSet += 2;
  219. while (nX < End && End > 0)
  220. {
  221. switch (FileBytes[OffSet])
  222. {
  223. default: //Unknown
  224. OffSet += 1;
  225. break;
  226. case 192: //No Colour
  227. nX += 2;
  228. x += FileBytes[OffSet + 3] << 8 | FileBytes[OffSet + 2];
  229. OffSet += 4;
  230. break;
  231. case 193: //Solid Colour
  232. nX += 2;
  233. Count = FileBytes[OffSet + 3] << 8 | FileBytes[OffSet + 2];
  234. OffSet += 4;
  235. for (int i = 0; i < Count; i++)
  236. {
  237. Pixels[0][(Y * OutputWidth + x) * 2] = FileBytes[OffSet];
  238. Pixels[0][(Y * OutputWidth + x) * 2 + 1] = FileBytes[OffSet + 1];
  239. OffSet += 2;
  240. if (x >= OutputWidth) continue;
  241. x++;
  242. }
  243. nX += Count;
  244. break;
  245. case 194: //Overlay Colour
  246. case 195:
  247. HasMask = true;
  248. nX += 2;
  249. Count = FileBytes[OffSet + 3] << 8 | FileBytes[OffSet + 2];
  250. OffSet += 4;
  251. for (int i = 0; i < Count; i++)
  252. {
  253. for (int j = 0; j < 2; j++)
  254. {
  255. Pixels[j][(Y * OutputWidth + x) * 2] = FileBytes[OffSet];
  256. Pixels[j][(Y * OutputWidth + x) * 2 + 1] = FileBytes[OffSet + 1];
  257. }
  258. OffSet += 2;
  259. if (x >= OutputWidth) continue;
  260. x++;
  261. }
  262. nX += Count;
  263. break;
  264. }
  265. }
  266. End++;
  267. Start = End;
  268. x = 0;
  269. }
  270. return Pixels;
  271. }
  272. public WeMadeImage(BinaryReader reader, byte nType)
  273. {
  274. if (reader.BaseStream.Position == 0) return;
  275. this.nType = nType;
  276. if (nType == 1)
  277. {
  278. bo16bit = (reader.ReadByte() == 5 ? true : false);
  279. reader.ReadBytes(3);
  280. }
  281. Width = reader.ReadInt16();
  282. Height = reader.ReadInt16();
  283. X = reader.ReadInt16();
  284. Y = reader.ReadInt16();
  285. nSize = Width * Height;
  286. switch (nType)
  287. {
  288. case 1:
  289. nSize = reader.ReadInt32();
  290. break;
  291. case 4:
  292. bo16bit = true;
  293. nSize = reader.ReadInt32();
  294. break;
  295. case 2:
  296. bo16bit = true;
  297. reader.ReadInt16();
  298. reader.ReadInt16();
  299. nSize = reader.ReadInt32();
  300. Width = (nSize < 6) ? (short)0 : Width;
  301. break;
  302. case 3:
  303. bo16bit = true;
  304. boHasShadow = reader.ReadByte() == 1 ? true : false;
  305. ShadowX = reader.ReadInt16();
  306. ShadowY = reader.ReadInt16();
  307. nSize = reader.ReadInt32() * 2;
  308. break;
  309. case 5:
  310. reader.ReadInt16();
  311. reader.ReadInt16();
  312. nSize = reader.ReadInt32();
  313. Width = (nSize < 6) ? (short)0 : Width;
  314. break;
  315. }
  316. Width = (nSize == 0) ? (short)0 : Width; //this makes sure blank images aren't being processed
  317. }
  318. public unsafe void CreateTexture(BinaryReader reader, int[] palette)
  319. {
  320. if (Width == 0 || Height == 0) return;
  321. Image = new Bitmap(Width, Height);
  322. MaskImage = new Bitmap(1, 1);
  323. BitmapData data = Image.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
  324. byte[] bytes = new byte[0];
  325. byte[] maskbytes = new byte[0];
  326. MemoryStream output;
  327. switch (nType)
  328. {
  329. case 0://wemade wil file uncompressed
  330. if (palette.Length > 256)
  331. {
  332. bo16bit = true;
  333. nSize = nSize * 2;
  334. }
  335. bytes = reader.ReadBytes(nSize);
  336. break;
  337. case 1://shanda wzl file compressed
  338. case 4://shanda miz file compressed
  339. output = new MemoryStream();
  340. Ionic.Zlib.ZlibStream deflateStream = new Ionic.Zlib.ZlibStream(output, Ionic.Zlib.CompressionMode.Decompress);
  341. deflateStream.Write(reader.ReadBytes(nSize), 0, nSize);
  342. bytes = output.ToArray();
  343. deflateStream.Close();
  344. output.Close();
  345. break;
  346. case 2:
  347. case 5:
  348. byte Compressed = reader.ReadByte();
  349. reader.ReadBytes(5);
  350. if (Compressed != 8)
  351. {
  352. bytes = reader.ReadBytes(nSize - 6);
  353. break;
  354. }
  355. MemoryStream input = new MemoryStream(reader.ReadBytes(nSize - 6));
  356. output = new MemoryStream();
  357. byte[] buffer = new byte[10];
  358. System.IO.Compression.DeflateStream decompress = new System.IO.Compression.DeflateStream(input, System.IO.Compression.CompressionMode.Decompress);
  359. int len;
  360. while ((len = decompress.Read(buffer, 0, buffer.Length)) > 0)
  361. {
  362. output.Write(buffer, 0, len);
  363. }
  364. bytes = output.ToArray();
  365. decompress.Close();
  366. output.Close();
  367. input.Close();
  368. break;
  369. case 3:
  370. MaskImage = new Bitmap(Width, Height);
  371. byte[][] DecodedPixels = DecompressWemadeMir3(reader, Width, Height, nSize);
  372. if (DecodedPixels != null)
  373. {
  374. bytes = DecodedPixels[0];
  375. if (HasMask)
  376. maskbytes = DecodedPixels[1];
  377. }
  378. else
  379. {
  380. HasMask = false;
  381. bytes = new byte[Width * Height * 2];
  382. }
  383. break;
  384. }
  385. int index = 0;
  386. if (nType == 5 && bytes.Length == Width * Height * 2)
  387. bo16bit = true;
  388. if (bytes.Length <= 1)
  389. {
  390. Image.UnlockBits(data);
  391. Image.Dispose();
  392. Image = null;
  393. MaskImage.Dispose();
  394. return;
  395. }
  396. int* scan0 = (int*)data.Scan0;
  397. {
  398. for (int y = Height - 1; y >= 0; y--)
  399. {
  400. for (int x = 0; x < Width; x++)
  401. {
  402. if (nType == 5 && !bo16bit)
  403. {
  404. scan0[y * Width + x] = BitConverter.ToInt32(bytes, index);
  405. index += 4;
  406. continue;
  407. }
  408. if (bo16bit)
  409. scan0[y * Width + x] = convert16bitTo32bit(bytes[index++] + (bytes[index++] << 8));
  410. else
  411. scan0[y * Width + x] = palette[bytes[index++]];
  412. }
  413. if (((nType == 1) || (nType == 4)) & (Width % 4 > 0))
  414. index += WidthBytes(bo16bit ? 16 : 8, Width) - (Width * (bo16bit ? 2 : 1));
  415. }
  416. }
  417. Image.UnlockBits(data);
  418. index = 0;
  419. if (HasMask)
  420. {
  421. BitmapData Maskdata = MaskImage.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
  422. int* maskscan0 = (int*)Maskdata.Scan0;
  423. {
  424. for (int y = Height - 1; y >= 0; y--)
  425. {
  426. for (int x = 0; x < Width; x++)
  427. maskscan0[y * Width + x] = convert16bitTo32bit(maskbytes[index++] + (maskbytes[index++] << 8));
  428. }
  429. }
  430. MaskImage.UnlockBits(Maskdata);
  431. }
  432. }
  433. }
  434. }
  435. }