PsdBinaryReader.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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-2017 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 System.Drawing;
  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. public class PsdBinaryReader : IDisposable
  26. {
  27. private BinaryReader reader;
  28. private Encoding encoding;
  29. public Stream BaseStream => reader.BaseStream;
  30. public PsdBinaryReader(Stream stream, PsdBinaryReader reader)
  31. : this (stream, reader.encoding)
  32. {
  33. }
  34. public PsdBinaryReader(Stream stream, Encoding encoding)
  35. {
  36. this.encoding = encoding;
  37. // ReadPascalString and ReadUnicodeString handle encoding explicitly.
  38. // BinaryReader.ReadString() is never called, so it is constructed with
  39. // ASCII encoding to make accidental usage obvious.
  40. reader = new BinaryReader(stream, Encoding.ASCII);
  41. }
  42. public byte ReadByte()
  43. {
  44. return reader.ReadByte();
  45. }
  46. public byte[] ReadBytes(int count)
  47. {
  48. return reader.ReadBytes(count);
  49. }
  50. public bool ReadBoolean()
  51. {
  52. return reader.ReadBoolean();
  53. }
  54. public Int16 ReadInt16()
  55. {
  56. var val = reader.ReadInt16();
  57. unsafe
  58. {
  59. Util.SwapBytes((byte*)&val, 2);
  60. }
  61. return val;
  62. }
  63. public Int32 ReadInt32()
  64. {
  65. var val = reader.ReadInt32();
  66. unsafe
  67. {
  68. Util.SwapBytes((byte*)&val, 4);
  69. }
  70. return val;
  71. }
  72. public Int64 ReadInt64()
  73. {
  74. var val = reader.ReadInt64();
  75. unsafe
  76. {
  77. Util.SwapBytes((byte*)&val, 8);
  78. }
  79. return val;
  80. }
  81. public UInt16 ReadUInt16()
  82. {
  83. var val = reader.ReadUInt16();
  84. unsafe
  85. {
  86. Util.SwapBytes((byte*)&val, 2);
  87. }
  88. return val;
  89. }
  90. public UInt32 ReadUInt32()
  91. {
  92. var val = reader.ReadUInt32();
  93. unsafe
  94. {
  95. Util.SwapBytes((byte*)&val, 4);
  96. }
  97. return val;
  98. }
  99. public UInt64 ReadUInt64()
  100. {
  101. var val = reader.ReadUInt64();
  102. unsafe
  103. {
  104. Util.SwapBytes((byte*)&val, 8);
  105. }
  106. return val;
  107. }
  108. //////////////////////////////////////////////////////////////////
  109. /// <summary>
  110. /// Read padding to get to the byte multiple for the block.
  111. /// </summary>
  112. /// <param name="startPosition">Starting position of the padded block.</param>
  113. /// <param name="padMultiple">Byte multiple that the block is padded to.</param>
  114. public void ReadPadding(long startPosition, int padMultiple)
  115. {
  116. // Pad to specified byte multiple
  117. var totalLength = reader.BaseStream.Position - startPosition;
  118. var padBytes = Util.GetPadding((int)totalLength, padMultiple);
  119. ReadBytes(padBytes);
  120. }
  121. public Rectangle ReadRectangle()
  122. {
  123. var rect = new Rectangle();
  124. rect.Y = ReadInt32();
  125. rect.X = ReadInt32();
  126. rect.Height = ReadInt32() - rect.Y;
  127. rect.Width = ReadInt32() - rect.X;
  128. return rect;
  129. }
  130. /// <summary>
  131. /// Read a fixed-length ASCII string.
  132. /// </summary>
  133. public string ReadAsciiChars(int count)
  134. {
  135. var bytes = reader.ReadBytes(count); ;
  136. var s = Encoding.ASCII.GetString(bytes);
  137. return s;
  138. }
  139. /// <summary>
  140. /// Read a Pascal string using the specified encoding.
  141. /// </summary>
  142. /// <param name="padMultiple">Byte multiple that the Pascal string is padded to.</param>
  143. public string ReadPascalString(int padMultiple)
  144. {
  145. var startPosition = reader.BaseStream.Position;
  146. byte stringLength = ReadByte();
  147. var bytes = ReadBytes(stringLength);
  148. ReadPadding(startPosition, padMultiple);
  149. // Default decoder uses best-fit fallback, so it will not throw any
  150. // exceptions if unknown characters are encountered.
  151. var str = encoding.GetString(bytes);
  152. return str;
  153. }
  154. public string ReadUnicodeString()
  155. {
  156. var numChars = ReadInt32();
  157. var length = 2 * numChars;
  158. var data = ReadBytes(length);
  159. var str = Encoding.BigEndianUnicode.GetString(data, 0, length);
  160. return str;
  161. }
  162. //////////////////////////////////////////////////////////////////
  163. # region IDisposable
  164. private bool disposed = false;
  165. public void Dispose()
  166. {
  167. Dispose(true);
  168. GC.SuppressFinalize(this);
  169. }
  170. protected virtual void Dispose(bool disposing)
  171. {
  172. // Check to see if Dispose has already been called.
  173. if (disposed)
  174. return;
  175. if (disposing)
  176. {
  177. if (reader != null)
  178. {
  179. // BinaryReader.Dispose() is protected.
  180. reader.Close();
  181. reader = null;
  182. }
  183. }
  184. disposed = true;
  185. }
  186. #endregion
  187. }
  188. }