LayerInfo.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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-2016 Tao Yue
  9. //
  10. // See LICENSE.txt for complete licensing and attribution information.
  11. //
  12. /////////////////////////////////////////////////////////////////////////////////
  13. using System;
  14. using System.Diagnostics;
  15. using System.IO;
  16. namespace PhotoshopFile
  17. {
  18. internal static class LayerInfoFactory
  19. {
  20. /// <summary>
  21. /// Loads the next LayerInfo record.
  22. /// </summary>
  23. /// <param name="reader">The file reader</param>
  24. /// <param name="psdFile">The PSD file.</param>
  25. /// <param name="globalLayerInfo">True if the LayerInfo record is being
  26. /// loaded from the end of the Layer and Mask Information section;
  27. /// false if it is being loaded from the end of a Layer record.</param>
  28. public static LayerInfo Load(PsdBinaryReader reader, PsdFile psdFile,
  29. bool globalLayerInfo, long fileEndPos)
  30. {
  31. Util.DebugMessage(reader.BaseStream, "Load, Begin, LayerInfo");
  32. // Some keys use a signature of 8B64, but the identity of these keys
  33. // is undocumented. We will therefore accept either signature.
  34. var signature = reader.ReadAsciiChars(4);
  35. if ((signature != "8BIM") && (signature != "8B64"))
  36. {
  37. throw new PsdInvalidException(
  38. "LayerInfo signature invalid, must be 8BIM or 8B64.");
  39. }
  40. var key = reader.ReadAsciiChars(4);
  41. var hasLongLength = LayerInfoUtil.HasLongLength(key, psdFile.IsLargeDocument);
  42. LayerInfo result = new RawLayerInfo("dummy");
  43. bool breakFromLoop = false;
  44. while (!breakFromLoop)
  45. {
  46. var baseStartPosition = reader.BaseStream.Position;
  47. var length = hasLongLength
  48. ? reader.ReadInt64()
  49. : reader.ReadInt32();
  50. var startPosition = reader.BaseStream.Position;
  51. switch (key)
  52. {
  53. case "Layr":
  54. case "Lr16":
  55. case "Lr32":
  56. result = new InfoLayers(reader, psdFile, key, length);
  57. break;
  58. case "lsct":
  59. case "lsdk":
  60. result = new LayerSectionInfo(reader, key, (int)length);
  61. break;
  62. case "luni":
  63. result = new LayerUnicodeName(reader);
  64. break;
  65. case "lyid":
  66. result = new LayerId(reader, key, length);
  67. break;
  68. default:
  69. result = new RawLayerInfo(reader, signature, key, length);
  70. break;
  71. }
  72. // May have additional padding applied.
  73. var endPosition = startPosition + length;
  74. if (reader.BaseStream.Position < endPosition)
  75. reader.BaseStream.Position = endPosition;
  76. // Documentation states that the length is even-padded. Actually:
  77. // 1. Most keys have 4-padded lengths.
  78. // 2. However, some keys (LMsk) have even-padded lengths.
  79. // 3. Other keys (Txt2, Lr16, Lr32) have unpadded lengths.
  80. //
  81. // Photoshop writes data that is always 4-padded, even when the stated
  82. // length is not a multiple of 4. The length mismatch seems to occur
  83. // only on global layer info. We do not read extra padding in other
  84. // cases because third-party programs are likely to follow the spec.
  85. if (globalLayerInfo)
  86. {
  87. reader.ReadPadding(startPosition, 4);
  88. }
  89. //try if we can read the next signature
  90. if (reader.BaseStream.Position < fileEndPos)
  91. {
  92. var nowPosition = reader.BaseStream.Position;
  93. signature = reader.ReadAsciiChars(4);
  94. if ((signature != "8BIM") && (signature != "8B64"))
  95. {
  96. hasLongLength = true;
  97. reader.BaseStream.Position = baseStartPosition;
  98. }
  99. else
  100. {
  101. reader.BaseStream.Position = nowPosition;
  102. breakFromLoop = true;
  103. }
  104. }
  105. else
  106. breakFromLoop = true;
  107. }
  108. Util.DebugMessage(reader.BaseStream, "Load, End, LayerInfo, {0}, {1}",
  109. result.Signature, result.Key);
  110. return result;
  111. }
  112. }
  113. internal static class LayerInfoUtil
  114. {
  115. internal static bool HasLongLength(string key, bool isLargeDocument)
  116. {
  117. if (!isLargeDocument)
  118. {
  119. return false;
  120. }
  121. //return false;
  122. switch (key)
  123. {
  124. case "LMsk":
  125. case "Lr16":
  126. case "Lr32":
  127. case "Layr":
  128. case "Mt16":
  129. case "Mt32":
  130. case "Mtrn":
  131. case "Alph":
  132. case "FMsk":
  133. case "lnk2":
  134. case "FEid":
  135. case "FXid":
  136. case "PxSD":
  137. case "lnkE": // Undocumented
  138. case "extn": // Undocumented
  139. case "cinf": // Undocumented
  140. return true;
  141. default:
  142. return false;
  143. }
  144. }
  145. }
  146. internal abstract class LayerInfo
  147. {
  148. public abstract string Signature { get; }
  149. public abstract string Key { get; }
  150. }
  151. }