SWFHeaderInfo.cs
上传用户:lctyggxszx
上传日期:2022-06-30
资源大小:280k
文件大小:9k
源码类别:

FlashMX/Flex源码

开发平台:

C#

  1. /*
  2. Darron Schall (darron@darronschall.com)
  3. July 7th, 2003
  4. File: SWFHeaderInfo.cs
  5. Note: Some ideas for this code were used from the flasm
  6. source code. See http://flasm.sourceforge.net
  7. for more information on flasm.
  8. Requires: This file requires "SharpZipLib", found at
  9. http://www.icsharpcode.net/OpenSource/SharpZipLib/ for
  10. decompressing compressed .swf files with the ZLib algorithm.
  11. Description:
  12. See the summary for the SWFHeaderInfo class
  13. */
  14. using System;
  15. using System.IO;
  16. namespace com.darronschall
  17. {
  18. /// <summary>
  19. /// SWFHeaderInfo is a class that exposes as properties the contents of 
  20. /// a .swf file header.  The path to the .swf file is passed into
  21. /// the constructor.  The Status property is useful for
  22. /// determining if the input was valid or not.  It is either "OK" if
  23. /// the swf header was successfully read, or an error message otherwise.
  24. /// 
  25. /// SWFHeaderInfo works for both compressed and uncompressed .swf  files.
  26. /// </summary>
  27. public class SWFHeaderInfo
  28. {
  29. private byte bitPos; // bitPos is our "position" in out bitBuffer "array", valid values are 0-8 (8 means get a new buffer)
  30. private byte bitBuffer;  // this is a byte that we'll be treating like an array
  31. uint nBits; // the number of bit used to store the data for the RECT type storing
  32. // the movies xMin, xMax, yMin, and yMax values
  33. private ICSharpCode.SharpZipLib.Zip.Compression.Inflater zipInflator; // used to decompressed swf
  34. Stream swf; // either a FileStream or MemoryStream
  35. // private internal data values
  36. private byte mVersion;
  37. private uint mLength;
  38. private uint mxMin;
  39. private uint mxMax;
  40. private uint myMin;
  41. private uint myMax;
  42. private ushort mFrameRate;
  43. private ushort mFrameCount;
  44. private bool mCompressed;
  45. private string mStatus;
  46. // public read-only (because no "set" defined) properties
  47. public byte Version 
  48. {
  49. get 
  50. {
  51. return mVersion;
  52. }
  53. }
  54. public uint Length 
  55. {
  56. get 
  57. {
  58. return mLength;
  59. }
  60. }
  61. public uint xMin 
  62. {
  63. get 
  64. {
  65. return mxMin;
  66. }
  67. }
  68. public uint xMax 
  69. {
  70. get 
  71. {
  72. return mxMax;
  73. }
  74. }
  75. public uint yMin 
  76. {
  77. get 
  78. {
  79. return myMin;
  80. }
  81. }
  82. public uint yMax 
  83. {
  84. get 
  85. {
  86. return myMax;
  87. }
  88. }
  89. public ushort FrameRate 
  90. {
  91. get 
  92. {
  93. return mFrameRate;
  94. }
  95. }
  96. public ushort FrameCount
  97. {
  98. get 
  99. {
  100. return mFrameCount;
  101. }
  102. }
  103. public bool Compressed 
  104. {
  105. get 
  106. {
  107. return mCompressed;
  108. }
  109. }
  110. public string Status 
  111. {
  112. get 
  113. {
  114. return mStatus;
  115. }
  116. }
  117. public SWFHeaderInfo(string path)
  118. {
  119. char first; // C if compressed, F otherwise
  120. // initialize
  121. mVersion = 0;
  122. mLength = 0;
  123. mxMin = 0;
  124. mxMax = 0;
  125. myMin = 0;
  126. mxMax = 0;
  127. mFrameRate = 0;
  128. mFrameCount = 0;
  129. mCompressed = false;
  130. mStatus = "No input specified";
  131. // attempt to open the swf file
  132. try 
  133. {
  134. swf = new FileStream(path, FileMode.Open);
  135. catch (Exception e) 
  136. {
  137. mStatus = "Error opening swf file";
  138. // We don't need to close the file here because there
  139. // was a problem opening it.
  140. //swf.Close();
  141. return;
  142. }
  143. bitPos = 8; // set out bitPos to be "out of bounds" so the first call to getBits reads in
  144. // a new byte from the file (the first byte)
  145. // try to read the first byte of the file
  146. try 
  147. {
  148. first = (char)getBits(swf,8);
  149. }
  150. catch (Exception e) 
  151. {
  152. mStatus = "Error reading first byte file";
  153. // close the swf file on error - 08/04/03
  154. swf.Close();
  155. return;
  156. }
  157. if (first == 'C') 
  158. {
  159. // compressed swf file
  160. mCompressed = true;
  161. swf = decompressSwf(swf);
  162. if (mStatus == "Error decompressing swf file") 
  163. {
  164. // trouble decompressing.. bail out! - 08/04/03
  165. swf.Close();
  166. return;
  167. }
  168. // reset our "array" index so the first call to getBits reads a new byte
  169. bitPos = 8;
  170. // attempt to get the first byte of the file
  171. try 
  172. {
  173. first = (char)getBits(swf,8);
  174. }
  175. catch (Exception e) 
  176. {
  177. mStatus = "Error reading first byte file";
  178. // close the swf file on error - 08/04/03
  179. swf.Close();
  180. return;
  181. }
  182. }
  183. // wrapped everything in a try/catch block "just in case" for
  184. // a little better error handling
  185. try 
  186. {
  187. // make sure the first 3 bytes are "FWS"
  188. if (first != 'F' || (char)getBits(swf,8) != 'W' || (char)getBits(swf,8) != 'S') 
  189. {
  190. // not a swf file!
  191. mStatus = "File specified does not seem to be a valid .swf file";
  192. // close the swf file on error - 08/04/03
  193. swf.Close();
  194. return;
  195. }
  196. // start collecting informatin
  197. mVersion = (byte)getBits(swf,8); 
  198. mLength = getDoubleWord(swf); 
  199. nBits = getBits(swf,5);
  200. mxMin = getBits(swf, nBits);
  201. mxMax = getBits(swf, nBits)/20;
  202. myMin = getBits(swf, nBits);
  203. myMax = getBits(swf, nBits)/20;
  204. mFrameRate =(ushort)( swf.ReadByte() << 8 | swf.ReadByte()); 
  205. mFrameCount = (ushort)(getWord(swf)); 
  206. mStatus = "OK";
  207. }
  208. catch (Exception e) 
  209. {
  210. mStatus = "Error reading .swf header information";
  211. return;
  212. }
  213. swf.Close();
  214. }
  215. // corrections for flash storing the byte values in little-endian format
  216. // ported from the flasm source code
  217. private uint getWord(Stream f) 
  218. {
  219. return (uint) (f.ReadByte() | f.ReadByte() << 8);
  220. }
  221. // corrections for flash storing the byte values in little-endian format
  222. // ported from the flasm source code
  223. private uint getDoubleWord(Stream f) 
  224. {
  225. return getWord(f) | (getWord(f) << 16);
  226. }
  227. // idea for this function borrowed from the flasm source code, but
  228. // the function code is my creation
  229. private uint getBits (Stream f, uint n)
  230. {
  231. uint returnbits = 0;
  232. while (true)
  233. {
  234. // do we have more bits to read?
  235. if (n >= 1) 
  236. {
  237. // yes, more bits to read....  do we have unread bits in our buffer?
  238. if (bitPos == 8) 
  239. {
  240. // no more bits to read in our buffer, lets get a new
  241. // buffer from f and reset the bitPos
  242. bitPos = 0;
  243. bitBuffer = (byte)f.ReadByte(); // read 8 bits at a time
  244. }
  245. // if we're here, we have more bits to read and 
  246. // we have unread bits in the buffer
  247. returnbits <<= 1; // shift the returnbit value left 1 place
  248. byte bitMask = (byte)(0x80 >> bitPos);
  249. // determine if the next bit we add to return bits should
  250. // be a 1 or a 0, based on the value of applying
  251. // the bitMask to the bitBuffer.  A quick example:
  252. // bitBuffer = 01011010
  253. // bitmask =   00001000
  254. // ~~~~~~~~~~~~~~~~~~~~  anding the bits together yeilds:
  255. //             00001000
  256. // and because the result is equal to the bitmask, we add
  257. // a 1 to the returnbits value.
  258. returnbits |= (bitBuffer & bitMask) == bitMask ? (uint)1 : (uint)0; 
  259. n -= 1; // one less bit to read
  260. bitPos += 1; // advance our "array" index
  261. }
  262. else 
  263. {
  264. //no more bits to read, return what we read from f
  265. return returnbits;
  266. }
  267. }
  268. }
  269. private Stream decompressSwf(Stream swf) 
  270. {
  271. // seek to after the 4th byte and read in 4 bytes to determine the 
  272. // size that the buffer needs to be to uncompressed the swf file
  273. swf.Seek(4, SeekOrigin.Begin);
  274. uint bufferSize = getDoubleWord(swf);
  275. // the uncompressedSwf byte array will be used as a MemoryStream
  276. byte[] uncompressedSwf = new byte[bufferSize];
  277. // only after the 8th bit is the ZLib compresseion applied, so just
  278. // copy the first 8 bits from the compressed swf to the uncompressed swf
  279. swf.Seek(0, SeekOrigin.Begin);
  280. swf.Read(uncompressedSwf, 0, 8);
  281. // set the first byte to be 'F' instead of 'C'
  282. uncompressedSwf[0] = (byte)0x46;
  283. zipInflator = new ICSharpCode.SharpZipLib.Zip.Compression.Inflater();
  284. // because the zipInflator takes a byte array, not a FileStream,
  285. // we need to declare a temporary byte array to use as the 
  286. // input for inflation
  287. byte[] tmpSwf = new byte[bufferSize - 8];
  288. // read the rest of the swf into our temporary byte array
  289. swf.Read(tmpSwf,0,(int)(bufferSize-8));
  290. // close the swf on disk because we have enough information in memory now
  291. swf.Close();
  292. zipInflator.SetInput(tmpSwf);
  293. if (zipInflator.Inflate(uncompressedSwf,8,(int)(bufferSize-8)) == 0) 
  294. {
  295. mStatus = "Error decompressing swf file";
  296. }
  297. // change our swf from a FileStream to a MemoryStream now, using the uncompressed swf data
  298. return new MemoryStream(uncompressedSwf);
  299. }
  300. /*[STAThread]
  301. public static void Main() 
  302. {
  303. SWFHeaderInfo s = new SWFHeaderInfo("C:\Development\SWFHeaderInfo\test.swf");
  304. Console.WriteLine(s.Status);
  305. if (s.Status == "OK") 
  306. {
  307. Console.WriteLine("Version: " + s.Version);
  308. Console.WriteLine("Length: " + s.Length);
  309. Console.WriteLine("xMin: " + s.xMin);
  310. Console.WriteLine("xMax: " + s.xMax);
  311. Console.WriteLine("yMin: " + s.xMin);
  312. Console.WriteLine("yMax: " + s.yMax);
  313. Console.WriteLine("FrameRate: " + s.FrameRate);
  314. Console.WriteLine("FrameCount: " + s.FrameCount);
  315. Console.WriteLine("Compressed: " + s.Compressed);
  316. }
  317. // keep the input on the screen
  318. Console.Read();
  319. }
  320. */
  321. }
  322. }