M3Z.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. using CommonLang.ByteOrder;
  2. using CommonLang.IO;
  3. using CommonUI_Unity3D.Impl;
  4. using System;
  5. using System.IO;
  6. using UnityEngine;
  7. namespace CommonUI_Unity3D.Src.M3Z
  8. {
  9. //////////////////////////////////////////////////////////////////////////
  10. // M3Z
  11. //////////////////////////////////////////////////////////////////////////
  12. public enum M3ZType
  13. {
  14. M3Z_TYPE_PNG = 0x00474e50,
  15. M3Z_TYPE_JPG = 0x0047504a,
  16. M3Z_TYPE_BMP = 0x00504d42,
  17. M3Z_TYPE_PVR4 = 0x34525650,
  18. M3Z_TYPE_PVR2 = 0x32525650,
  19. M3Z_TYPE_PVR1 = 0x31525650,
  20. M3Z_TYPE_PVRA = 0x41525650,
  21. M3Z_TYPE_PKM1 = 0x314d4b50,
  22. M3Z_TYPE_PKMA = 0x414d4b50,
  23. M3Z_TYPE_ATC_E = 0x45435441,
  24. M3Z_TYPE_ATC_I = 0x49435441,
  25. M3Z_TYPE_ATC_RGB = 0x33435441,
  26. M3Z_TYPE_ETC1 = 0x31435445,
  27. M3Z_TYPE_ETCA = 0x41435445,
  28. M3Z_TYPE_RGBA8 = 0x41424752,
  29. M3Z_TYPE_A8 = 0x00003841,
  30. M3Z_TYPE_DXT1 = 0x31545844,
  31. M3Z_TYPE_DXT3 = 0x33545844,
  32. M3Z_TYPE_DXT5 = 0x35545844,
  33. }
  34. public class M3ZHeader
  35. {
  36. public const uint M3Z_HEADER = 0x5a33464d;
  37. /**文件头*/
  38. public uint header { get; private set; }
  39. /**文件尺寸*/
  40. public uint version { get; private set; }
  41. /**原始图片宽*/
  42. public int srcWidth { get; private set; }
  43. /**原始图片高*/
  44. public int srcHeight { get; private set; }
  45. /**原始图片是否包含半透明*/
  46. public bool srcHasAlpha { get; private set; }
  47. /**附加数据*/
  48. public string extUTFData { get; private set; }
  49. /**纹理数量*/
  50. public int trunkCount { get; private set; }
  51. /**纹理块*/
  52. public M3ZTrunk[] trunks { get; private set; }
  53. public M3ZHeader(Stream data)
  54. {
  55. this.header = LittleEdian.GetU32(data);
  56. if (header != M3Z_HEADER)
  57. {
  58. throw new Exception("Invalid M3Z data");
  59. }
  60. this.version = LittleEdian.GetU32(data);
  61. const uint v_0100 = 0x00000100;
  62. if (version == v_0100)
  63. {
  64. srcWidth = LittleEdian.GetS32(data);
  65. srcHeight = LittleEdian.GetS32(data);
  66. srcHasAlpha = LittleEdian.GetBool(data);
  67. extUTFData = LittleEdian.GetUTF(data);
  68. trunkCount = LittleEdian.GetS32(data);
  69. trunks = new M3ZTrunk[trunkCount];
  70. for (int i = 0; i < trunkCount; i++)
  71. {
  72. trunks[i] = new M3ZTrunk(data, version);
  73. }
  74. }
  75. else
  76. {
  77. // 君王2老M3Z文件格式代码
  78. srcWidth = LittleEdian.GetS32(data);
  79. srcHeight = LittleEdian.GetS32(data);
  80. srcHasAlpha = LittleEdian.GetBool(data);
  81. trunkCount = LittleEdian.GetS32(data);
  82. trunks = new M3ZTrunk[trunkCount];
  83. for (int i = 0; i < trunkCount; i++)
  84. {
  85. trunks[i] = new M3ZTrunk(data, version);
  86. }
  87. }
  88. }
  89. }
  90. public class M3ZTrunk
  91. {
  92. /// <summary>
  93. /// 类型
  94. /// </summary>
  95. public M3ZType type { get; private set; }
  96. public uint flags { get; private set; }
  97. /// <summary>
  98. /// 是否包含半透明
  99. /// </summary>
  100. public bool hasAlpha { get; private set; }
  101. /// <summary>
  102. /// 二的冥宽
  103. /// </summary>
  104. public int pixelW { get; private set; }
  105. /// <summary>
  106. /// 二的冥高
  107. /// </summary>
  108. public int pixelH { get; private set; }
  109. /// <summary>
  110. /// 实际像素点宽
  111. /// </summary>
  112. public int realPixelW { get; private set; }
  113. /// <summary>
  114. /// 实际像素点高
  115. /// </summary>
  116. public int realPixelH { get; private set; }
  117. /// <summary>
  118. /// 扩展数据
  119. /// </summary>
  120. public string extUTFData { get; private set; }
  121. /// <summary>
  122. /// 数据段尺寸
  123. /// </summary>
  124. public int fileSize { get; private set; }
  125. public ICompressTextureData texData { get; private set; }
  126. public M3ZTrunk(Stream data, uint version)
  127. {
  128. const uint v_0100 = 0x00000100;
  129. if (version == v_0100)
  130. {
  131. this.type = (M3ZType)LittleEdian.GetU32(data);
  132. this.hasAlpha = LittleEdian.GetBool(data);
  133. this.pixelW = LittleEdian.GetS32(data);
  134. this.pixelH = LittleEdian.GetS32(data);
  135. this.realPixelW = LittleEdian.GetS32(data);
  136. this.realPixelH = LittleEdian.GetS32(data);
  137. this.extUTFData = LittleEdian.GetUTF(data);
  138. this.fileSize = LittleEdian.GetS32(data);
  139. }
  140. else
  141. {
  142. this.type = (M3ZType)LittleEdian.GetU32(data);
  143. this.flags = LittleEdian.GetU32(data);
  144. this.hasAlpha = LittleEdian.GetBool(data);
  145. this.pixelW = LittleEdian.GetS32(data);
  146. this.pixelH = LittleEdian.GetS32(data);
  147. this.realPixelW = pixelW;
  148. this.realPixelH = pixelH;
  149. this.fileSize = LittleEdian.GetS32(data);
  150. }
  151. switch (type)
  152. {
  153. case M3ZType.M3Z_TYPE_PVR2:
  154. case M3ZType.M3Z_TYPE_PVR4:
  155. case M3ZType.M3Z_TYPE_PVR1:
  156. case M3ZType.M3Z_TYPE_PVRA:
  157. this.texData = new PVRTexHeader();
  158. break;
  159. case M3ZType.M3Z_TYPE_ETC1:
  160. case M3ZType.M3Z_TYPE_ETCA:
  161. this.texData = new KTXTexHeader();
  162. break;
  163. case M3ZType.M3Z_TYPE_PKM1:
  164. case M3ZType.M3Z_TYPE_PKMA:
  165. this.texData = new PKMTexHeader();
  166. break;
  167. default:
  168. this.texData = new UnknowTexHeader();
  169. break;
  170. }
  171. if (texData != null)
  172. {
  173. texData.Decode(this, data);
  174. }
  175. }
  176. public Texture2D LoadRawTextureData()
  177. {
  178. if (texData != null)
  179. {
  180. return texData.LoadRawTextureData(this);
  181. }
  182. return null;
  183. }
  184. public static TextureFormat GetTextureFormat(M3ZType mtype)
  185. {
  186. switch (mtype)
  187. {
  188. case M3ZType.M3Z_TYPE_PNG:
  189. case M3ZType.M3Z_TYPE_JPG:
  190. case M3ZType.M3Z_TYPE_BMP:
  191. return TextureFormat.RGBA32;
  192. case M3ZType.M3Z_TYPE_PVR2:
  193. return TextureFormat.PVRTC_RGBA2;
  194. case M3ZType.M3Z_TYPE_PVR4:
  195. case M3ZType.M3Z_TYPE_PVR1:
  196. case M3ZType.M3Z_TYPE_PVRA:
  197. return TextureFormat.PVRTC_RGBA4;
  198. case M3ZType.M3Z_TYPE_PKM1:
  199. case M3ZType.M3Z_TYPE_PKMA:
  200. return TextureFormat.ETC_RGB4;
  201. case M3ZType.M3Z_TYPE_ATC_E:
  202. case M3ZType.M3Z_TYPE_ATC_I:
  203. case M3ZType.M3Z_TYPE_ATC_RGB:
  204. return TextureFormat.ATC_RGB4;
  205. case M3ZType.M3Z_TYPE_ETC1:
  206. case M3ZType.M3Z_TYPE_ETCA:
  207. return TextureFormat.ETC_RGB4;
  208. case M3ZType.M3Z_TYPE_RGBA8:
  209. return TextureFormat.RGBA32;
  210. case M3ZType.M3Z_TYPE_A8:
  211. return TextureFormat.Alpha8;
  212. case M3ZType.M3Z_TYPE_DXT1:
  213. return TextureFormat.DXT1;
  214. case M3ZType.M3Z_TYPE_DXT3:
  215. return TextureFormat.DXT5;
  216. case M3ZType.M3Z_TYPE_DXT5:
  217. return TextureFormat.DXT5;
  218. }
  219. return TextureFormat.RGBA32;
  220. }
  221. }
  222. public interface ICompressTextureData
  223. {
  224. byte[] RawData { get; }
  225. void Decode(M3ZTrunk trunk, Stream stream);
  226. void Encode(Stream stream);
  227. Texture2D LoadRawTextureData(M3ZTrunk trunk);
  228. }
  229. public struct UnknowTexHeader : ICompressTextureData
  230. {
  231. public byte[] rawData;
  232. public byte[] RawData { get { return rawData; } }
  233. public void Decode(M3ZTrunk trunk, Stream stream)
  234. {
  235. this.rawData = new byte[trunk.fileSize];
  236. IOUtil.ReadToEnd(stream, rawData, 0, rawData.Length);
  237. }
  238. public void Encode(Stream stream)
  239. {
  240. IOUtil.WriteToEnd(stream, rawData, 0, rawData.Length);
  241. }
  242. public Texture2D LoadRawTextureData(M3ZTrunk trunk)
  243. {
  244. Texture2D tex = new Texture2D(trunk.pixelW, trunk.pixelH, M3ZTrunk.GetTextureFormat(trunk.type), false, true);
  245. tex.LoadRawTextureData(rawData);
  246. tex.Apply(false, true);
  247. return tex;
  248. }
  249. }
  250. public struct PVRTexHeader : ICompressTextureData
  251. {
  252. public const int PVR_HEADER_SIZE = 52;
  253. public uint headerLength;
  254. public uint height;
  255. public uint width;
  256. public uint numMipmaps;
  257. public uint flags;
  258. public uint dataLength;
  259. public uint bpp;
  260. public uint bitmaskRed;
  261. public uint bitmaskGreen;
  262. public uint bitmaskBlue;
  263. public uint bitmaskAlpha;
  264. public uint pvrTag;
  265. public uint numSurfs;
  266. public byte[] rawData;
  267. public byte[] RawData { get { return rawData; } }
  268. public void Decode(M3ZTrunk trunk, Stream stream)
  269. {
  270. this.headerLength = LittleEdian.GetU32(stream);
  271. this.height = LittleEdian.GetU32(stream);
  272. this.width = LittleEdian.GetU32(stream);
  273. this.numMipmaps = LittleEdian.GetU32(stream);
  274. this.flags = LittleEdian.GetU32(stream);
  275. this.dataLength = LittleEdian.GetU32(stream);
  276. this.bpp = LittleEdian.GetU32(stream);
  277. this.bitmaskRed = LittleEdian.GetU32(stream);
  278. this.bitmaskGreen = LittleEdian.GetU32(stream);
  279. this.bitmaskBlue = LittleEdian.GetU32(stream);
  280. this.bitmaskAlpha = LittleEdian.GetU32(stream);
  281. this.pvrTag = LittleEdian.GetU32(stream);
  282. this.numSurfs = LittleEdian.GetU32(stream);
  283. this.rawData = new byte[dataLength];
  284. IOUtil.ReadToEnd(stream, rawData, 0, rawData.Length);
  285. }
  286. public void Encode(Stream stream)
  287. {
  288. LittleEdian.PutU32(stream, this.headerLength);
  289. LittleEdian.PutU32(stream, this.height);
  290. LittleEdian.PutU32(stream, this.width);
  291. LittleEdian.PutU32(stream, this.numMipmaps);
  292. LittleEdian.PutU32(stream, this.flags);
  293. LittleEdian.PutU32(stream, this.dataLength);
  294. LittleEdian.PutU32(stream, this.bpp);
  295. LittleEdian.PutU32(stream, this.bitmaskRed);
  296. LittleEdian.PutU32(stream, this.bitmaskGreen);
  297. LittleEdian.PutU32(stream, this.bitmaskBlue);
  298. LittleEdian.PutU32(stream, this.bitmaskAlpha);
  299. LittleEdian.PutU32(stream, this.pvrTag);
  300. LittleEdian.PutU32(stream, this.numSurfs);
  301. IOUtil.WriteToEnd(stream, rawData, 0, rawData.Length);
  302. }
  303. public Texture2D LoadRawTextureData(M3ZTrunk trunk)
  304. {
  305. Texture2D tex = new Texture2D(trunk.pixelW, trunk.pixelH, M3ZTrunk.GetTextureFormat(trunk.type), false, true);
  306. tex.LoadRawTextureData(rawData);
  307. tex.Apply(false, true);
  308. return tex;
  309. }
  310. }
  311. public struct PKMTexHeader : ICompressTextureData
  312. {
  313. public const int PKM_HEADER_SIZE = 16;
  314. public byte[] MagicNumber; // 4 byte magic number: "PKM "
  315. public byte[] Version; // 2 byte version "10"
  316. public byte[] DataType; // 2 byte data type: 0 (ETC1_RGB_NO_MIPMAPS)
  317. public ushort ExtWidth; // 16 bit big endian extended width
  318. public ushort ExtHeight; // 16 bit big endian extended height
  319. public ushort SrcWidth; // 16 bit big endian original width
  320. public ushort SrcHeight; // 16 bit big endian original height
  321. public byte[] rawData;
  322. public byte[] RawData { get { return rawData; } }
  323. public void Decode(M3ZTrunk trunk, Stream stream)
  324. {
  325. this.MagicNumber = IOUtil.ReadExpect(stream, 4);
  326. this.Version = IOUtil.ReadExpect(stream, 2);
  327. this.DataType = IOUtil.ReadExpect(stream, 2);
  328. this.ExtWidth = BigEdian.GetU16(stream);
  329. this.ExtHeight = BigEdian.GetU16(stream);
  330. this.SrcWidth = BigEdian.GetU16(stream);
  331. this.SrcHeight = BigEdian.GetU16(stream);
  332. this.rawData = new byte[trunk.fileSize - PKM_HEADER_SIZE];
  333. IOUtil.ReadToEnd(stream, rawData, 0, rawData.Length);
  334. }
  335. public void Encode(Stream stream)
  336. {
  337. IOUtil.WriteToEnd(stream, this.MagicNumber, 0, 4);
  338. IOUtil.WriteToEnd(stream, this.Version, 0, 2);
  339. IOUtil.WriteToEnd(stream, this.DataType, 0, 2);
  340. BigEdian.PutU16(stream, this.ExtWidth);
  341. BigEdian.PutU16(stream, this.ExtHeight);
  342. BigEdian.PutU16(stream, this.SrcWidth);
  343. BigEdian.PutU16(stream, this.SrcHeight);
  344. IOUtil.WriteToEnd(stream, rawData, 0, rawData.Length);
  345. }
  346. public Texture2D LoadRawTextureData(M3ZTrunk trunk)
  347. {
  348. Texture2D tex = new Texture2D(trunk.pixelW, trunk.pixelH, M3ZTrunk.GetTextureFormat(trunk.type), false, true);
  349. tex.LoadRawTextureData(rawData);
  350. tex.Apply(false, true);
  351. return tex;
  352. }
  353. }
  354. public struct KTXTexHeader : ICompressTextureData
  355. {
  356. public const int KTX_HEADER_SIZE = 52 + 12;
  357. public static byte[] KTX_IDENTIFIER_REF = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
  358. public byte[] identifier;
  359. public uint endianness;
  360. public uint glType;
  361. public uint glTypeSize;
  362. public uint glFormat;
  363. public uint glInternalFormat;
  364. public uint glBaseInternalFormat;
  365. public uint pixelWidth;
  366. public uint pixelHeight;
  367. public uint pixelDepth;
  368. public uint numberOfArrayElements;
  369. public uint numberOfFaces;
  370. public uint numberOfMipmapLevels;
  371. public uint bytesOfKeyValueData;
  372. public byte[] rawData;
  373. public byte[] RawData { get { return rawData; } }
  374. public void Decode(M3ZTrunk trunk, Stream stream)
  375. {
  376. this.identifier = IOUtil.ReadExpect(stream, 12);
  377. this.endianness = LittleEdian.GetU32(stream);
  378. this.glType = LittleEdian.GetU32(stream);
  379. this.glTypeSize = LittleEdian.GetU32(stream);
  380. this.glFormat = LittleEdian.GetU32(stream);
  381. this.glInternalFormat = LittleEdian.GetU32(stream);
  382. this.glBaseInternalFormat = LittleEdian.GetU32(stream);
  383. this.pixelWidth = LittleEdian.GetU32(stream);
  384. this.pixelHeight = LittleEdian.GetU32(stream);
  385. this.pixelDepth = LittleEdian.GetU32(stream);
  386. this.numberOfArrayElements = LittleEdian.GetU32(stream);
  387. this.numberOfFaces = LittleEdian.GetU32(stream);
  388. this.numberOfMipmapLevels = LittleEdian.GetU32(stream);
  389. this.bytesOfKeyValueData = LittleEdian.GetU32(stream);
  390. stream.Position += this.bytesOfKeyValueData;
  391. uint imageSize = LittleEdian.GetU32(stream);
  392. this.rawData = new byte[imageSize];
  393. IOUtil.ReadToEnd(stream, rawData, 0, rawData.Length);
  394. }
  395. public void Encode(Stream stream)
  396. {
  397. IOUtil.WriteToEnd(stream, this.identifier, 0, 12);
  398. LittleEdian.PutU32(stream, endianness);
  399. LittleEdian.PutU32(stream, glType);
  400. LittleEdian.PutU32(stream, glTypeSize);
  401. LittleEdian.PutU32(stream, glFormat);
  402. LittleEdian.PutU32(stream, glInternalFormat);
  403. LittleEdian.PutU32(stream, glBaseInternalFormat);
  404. LittleEdian.PutU32(stream, pixelWidth);
  405. LittleEdian.PutU32(stream, pixelHeight);
  406. LittleEdian.PutU32(stream, pixelDepth);
  407. LittleEdian.PutU32(stream, numberOfArrayElements);
  408. LittleEdian.PutU32(stream, numberOfFaces);
  409. LittleEdian.PutU32(stream, numberOfMipmapLevels);
  410. LittleEdian.PutU32(stream, bytesOfKeyValueData);
  411. LittleEdian.PutU32(stream, (uint)rawData.Length);
  412. IOUtil.WriteToEnd(stream, rawData, 0, rawData.Length);
  413. }
  414. public Texture2D LoadRawTextureData(M3ZTrunk trunk)
  415. {
  416. Texture2D tex = new Texture2D(trunk.pixelW, trunk.pixelH, M3ZTrunk.GetTextureFormat(trunk.type), false, true);
  417. tex.LoadRawTextureData(rawData);
  418. tex.Apply(false, true);
  419. return tex;
  420. }
  421. }
  422. public static class G3ZStream
  423. {
  424. public static Stream DecompressToStream(byte[] data)
  425. {
  426. int pos = 0;
  427. int Head = (int)LittleEdian.GetU32(data, ref pos);
  428. int SrcSize = (int)LittleEdian.GetU32(data, ref pos);
  429. byte[] dst = new byte[SrcSize];
  430. UnityDriver.Platform.NativeDecompressMemory(
  431. new ArraySegment<byte>(data, pos, data.Length - pos),
  432. new ArraySegment<byte>(dst, 0, dst.Length));
  433. return new MemoryStream(dst);
  434. }
  435. }
  436. }