123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /////////////////////////////////////////////////////////////////////////////////
- //
- // Photoshop PSD FileType Plugin for Paint.NET
- // http://psdplugin.codeplex.com/
- //
- // This software is provided under the MIT License:
- // Copyright (c) 2006-2007 Frank Blumenberg
- // Copyright (c) 2010-2013 Tao Yue
- //
- // Portions of this file are provided under the BSD 3-clause License:
- // Copyright (c) 2006, Jonas Beckeman
- //
- // See LICENSE.txt for complete licensing and attribution information.
- //
- /////////////////////////////////////////////////////////////////////////////////
-
- using System;
- using PDNWrapper;
- using System.IO;
- using System.Text;
-
- namespace PhotoshopFile
- {
- /// <summary>
- /// Reads PSD data types in big-endian byte order.
- /// </summary>
- internal class PsdBinaryReader : IDisposable
- {
- private BinaryReader reader;
- private Encoding encoding;
-
- public Stream BaseStream
- {
- get { return reader.BaseStream; }
- }
-
- public PsdBinaryReader(Stream stream, PsdBinaryReader reader)
- : this(stream, reader.encoding)
- {
- }
-
- public PsdBinaryReader(Stream stream, Encoding encoding)
- {
- this.encoding = encoding;
-
- // ReadPascalString and ReadUnicodeString handle encoding explicitly.
- // BinaryReader.ReadString() is never called, so it is constructed with
- // ASCII encoding to make accidental usage obvious.
- reader = new BinaryReader(stream, Encoding.ASCII);
- }
-
- public byte ReadByte()
- {
- return reader.ReadByte();
- }
-
- public byte[] ReadBytes(int count)
- {
- return reader.ReadBytes(count);
- }
-
- public bool ReadBoolean()
- {
- return reader.ReadBoolean();
- }
-
- public Int16 ReadInt16()
- {
- var val = reader.ReadInt16();
- byte[] b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 2);
- }
- val = BitConverter.ToInt16(b, 0);
- return val;
- }
-
- public Int32 ReadInt32()
- {
- var val = reader.ReadInt32();
- byte[] b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 4);
- }
- val = BitConverter.ToInt32(b, 0);
- return val;
- }
-
- public double ReadDouble()
- {
- var val = reader.ReadDouble();
- byte[] b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 8);
- }
- val = BitConverter.ToDouble(b, 0);
- return val;
- }
-
- public Int64 ReadInt64()
- {
- var val = reader.ReadInt64();
- var b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 8);
- }
- val = BitConverter.ToInt64(b, 0);
- return val;
- }
-
- public UInt16 ReadUInt16()
- {
- var val = reader.ReadUInt16();
- var b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 2);
- }
- val = BitConverter.ToUInt16(b, 0);
- return val;
- }
-
- public UInt32 ReadUInt32()
- {
- var val = reader.ReadUInt32();
- var b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 4);
- }
- val = BitConverter.ToUInt32(b, 0);
- return val;
- }
-
- public UInt64 ReadUInt64()
- {
- var val = reader.ReadUInt64();
- var b = BitConverter.GetBytes(val);
- {
- Util.SwapBytes(b, 0, 8);
- }
- val = BitConverter.ToUInt64(b, 0);
- return val;
- }
-
- //////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// Read padding to get to the byte multiple for the block.
- /// </summary>
- /// <param name="startPosition">Starting position of the padded block.</param>
- /// <param name="padMultiple">Byte multiple that the block is padded to.</param>
- public void ReadPadding(long startPosition, int padMultiple)
- {
- // Pad to specified byte multiple
- var totalLength = reader.BaseStream.Position - startPosition;
- var padBytes = Util.GetPadding((int)totalLength, padMultiple);
- ReadBytes(padBytes);
- }
-
- public Rectangle ReadRectangle()
- {
- var rect = new Rectangle();
- rect.Y = ReadInt32();
- rect.X = ReadInt32();
- rect.Height = ReadInt32() - rect.Y;
- rect.Width = ReadInt32() - rect.X;
- return rect;
- }
-
- /// <summary>
- /// Read a fixed-length ASCII string.
- /// </summary>
- public string ReadAsciiChars(int count)
- {
- var bytes = reader.ReadBytes(count);
- var s = Encoding.ASCII.GetString(bytes);
- return s;
- }
-
- /// <summary>
- /// Read a Pascal string using the specified encoding.
- /// </summary>
- /// <param name="padMultiple">Byte multiple that the Pascal string is padded to.</param>
- public string ReadPascalString(int padMultiple)
- {
- var startPosition = reader.BaseStream.Position;
-
- byte stringLength = ReadByte();
- var bytes = ReadBytes(stringLength);
- ReadPadding(startPosition, padMultiple);
-
- // Default decoder uses best-fit fallback, so it will not throw any
- // exceptions if unknown characters are encountered.
- var str = encoding.GetString(bytes);
- return str;
- }
-
- public string ReadUnicodeString()
- {
- var numChars = ReadInt32();
- var length = 2 * numChars;
- var data = ReadBytes(length);
- var str = Encoding.BigEndianUnicode.GetString(data, 0, length);
-
- return str;
- }
-
- //////////////////////////////////////////////////////////////////
-
- #region IDisposable
-
- private bool disposed = false;
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- // Check to see if Dispose has already been called.
- if (disposed)
- return;
-
- if (disposing)
- {
- if (reader != null)
- {
- // BinaryReader.Dispose() is protected.
- reader.Close();
- reader = null;
- }
- }
-
- disposed = true;
- }
-
- #endregion
- }
- }
|