暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PsdBinaryReader.cs 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Photoshop PSD FileType Plugin for Paint.NET
  4. // http://psdplugin.codeplex.com/
  5. //
  6. // This software is provided under the MIT License:
  7. // Copyright (c) 2006-2007 Frank Blumenberg
  8. // Copyright (c) 2010-2013 Tao Yue
  9. //
  10. // Portions of this file are provided under the BSD 3-clause License:
  11. // Copyright (c) 2006, Jonas Beckeman
  12. //
  13. // See LICENSE.txt for complete licensing and attribution information.
  14. //
  15. /////////////////////////////////////////////////////////////////////////////////
  16. using System;
  17. using PDNWrapper;
  18. using System.IO;
  19. using System.Text;
  20. namespace PhotoshopFile
  21. {
  22. /// <summary>
  23. /// Reads PSD data types in big-endian byte order.
  24. /// </summary>
  25. internal class PsdBinaryReader : IDisposable
  26. {
  27. private BinaryReader reader;
  28. private Encoding encoding;
  29. public Stream BaseStream
  30. {
  31. get { return reader.BaseStream; }
  32. }
  33. public PsdBinaryReader(Stream stream, PsdBinaryReader reader)
  34. : this(stream, reader.encoding)
  35. {
  36. }
  37. public PsdBinaryReader(Stream stream, Encoding encoding)
  38. {
  39. this.encoding = encoding;
  40. // ReadPascalString and ReadUnicodeString handle encoding explicitly.
  41. // BinaryReader.ReadString() is never called, so it is constructed with
  42. // ASCII encoding to make accidental usage obvious.
  43. reader = new BinaryReader(stream, Encoding.ASCII);
  44. }
  45. public byte ReadByte()
  46. {
  47. return reader.ReadByte();
  48. }
  49. public byte[] ReadBytes(int count)
  50. {
  51. return reader.ReadBytes(count);
  52. }
  53. public bool ReadBoolean()
  54. {
  55. return reader.ReadBoolean();
  56. }
  57. public Int16 ReadInt16()
  58. {
  59. var val = reader.ReadInt16();
  60. byte[] b = BitConverter.GetBytes(val);
  61. {
  62. Util.SwapBytes(b, 0, 2);
  63. }
  64. val = BitConverter.ToInt16(b, 0);
  65. return val;
  66. }
  67. public Int32 ReadInt32()
  68. {
  69. var val = reader.ReadInt32();
  70. byte[] b = BitConverter.GetBytes(val);
  71. {
  72. Util.SwapBytes(b, 0, 4);
  73. }
  74. val = BitConverter.ToInt32(b, 0);
  75. return val;
  76. }
  77. public double ReadDouble()
  78. {
  79. var val = reader.ReadDouble();
  80. byte[] b = BitConverter.GetBytes(val);
  81. {
  82. Util.SwapBytes(b, 0, 8);
  83. }
  84. val = BitConverter.ToDouble(b, 0);
  85. return val;
  86. }
  87. public Int64 ReadInt64()
  88. {
  89. var val = reader.ReadInt64();
  90. var b = BitConverter.GetBytes(val);
  91. {
  92. Util.SwapBytes(b, 0, 8);
  93. }
  94. val = BitConverter.ToInt64(b, 0);
  95. return val;
  96. }
  97. public UInt16 ReadUInt16()
  98. {
  99. var val = reader.ReadUInt16();
  100. var b = BitConverter.GetBytes(val);
  101. {
  102. Util.SwapBytes(b, 0, 2);
  103. }
  104. val = BitConverter.ToUInt16(b, 0);
  105. return val;
  106. }
  107. public UInt32 ReadUInt32()
  108. {
  109. var val = reader.ReadUInt32();
  110. var b = BitConverter.GetBytes(val);
  111. {
  112. Util.SwapBytes(b, 0, 4);
  113. }
  114. val = BitConverter.ToUInt32(b, 0);
  115. return val;
  116. }
  117. public UInt64 ReadUInt64()
  118. {
  119. var val = reader.ReadUInt64();
  120. var b = BitConverter.GetBytes(val);
  121. {
  122. Util.SwapBytes(b, 0, 8);
  123. }
  124. val = BitConverter.ToUInt64(b, 0);
  125. return val;
  126. }
  127. //////////////////////////////////////////////////////////////////
  128. /// <summary>
  129. /// Read padding to get to the byte multiple for the block.
  130. /// </summary>
  131. /// <param name="startPosition">Starting position of the padded block.</param>
  132. /// <param name="padMultiple">Byte multiple that the block is padded to.</param>
  133. public void ReadPadding(long startPosition, int padMultiple)
  134. {
  135. // Pad to specified byte multiple
  136. var totalLength = reader.BaseStream.Position - startPosition;
  137. var padBytes = Util.GetPadding((int)totalLength, padMultiple);
  138. ReadBytes(padBytes);
  139. }
  140. public Rectangle ReadRectangle()
  141. {
  142. var rect = new Rectangle();
  143. rect.Y = ReadInt32();
  144. rect.X = ReadInt32();
  145. rect.Height = ReadInt32() - rect.Y;
  146. rect.Width = ReadInt32() - rect.X;
  147. return rect;
  148. }
  149. /// <summary>
  150. /// Read a fixed-length ASCII string.
  151. /// </summary>
  152. public string ReadAsciiChars(int count)
  153. {
  154. var bytes = reader.ReadBytes(count);
  155. var s = Encoding.ASCII.GetString(bytes);
  156. return s;
  157. }
  158. /// <summary>
  159. /// Read a Pascal string using the specified encoding.
  160. /// </summary>
  161. /// <param name="padMultiple">Byte multiple that the Pascal string is padded to.</param>
  162. public string ReadPascalString(int padMultiple)
  163. {
  164. var startPosition = reader.BaseStream.Position;
  165. byte stringLength = ReadByte();
  166. var bytes = ReadBytes(stringLength);
  167. ReadPadding(startPosition, padMultiple);
  168. // Default decoder uses best-fit fallback, so it will not throw any
  169. // exceptions if unknown characters are encountered.
  170. var str = encoding.GetString(bytes);
  171. return str;
  172. }
  173. public string ReadUnicodeString()
  174. {
  175. var numChars = ReadInt32();
  176. var length = 2 * numChars;
  177. var data = ReadBytes(length);
  178. var str = Encoding.BigEndianUnicode.GetString(data, 0, length);
  179. return str;
  180. }
  181. //////////////////////////////////////////////////////////////////
  182. #region IDisposable
  183. private bool disposed = false;
  184. public void Dispose()
  185. {
  186. Dispose(true);
  187. GC.SuppressFinalize(this);
  188. }
  189. protected virtual void Dispose(bool disposing)
  190. {
  191. // Check to see if Dispose has already been called.
  192. if (disposed)
  193. return;
  194. if (disposing)
  195. {
  196. if (reader != null)
  197. {
  198. // BinaryReader.Dispose() is protected.
  199. reader.Close();
  200. reader = null;
  201. }
  202. }
  203. disposed = true;
  204. }
  205. #endregion
  206. }
  207. }