/// <summary> /// Loads the next LayerInfo record. /// </summary> /// <param name="reader">The file reader</param> /// <param name="psdFile">The PSD file.</param> /// <param name="globalLayerInfo">True if the LayerInfo record is being /// loaded from the end of the Layer and Mask Information section; /// false if it is being loaded from the end of a Layer record.</param> public static LayerInfo Load(PsdBinaryReader reader, PsdFile psdFile, bool globalLayerInfo, long fileEndPos) { Util.DebugMessage(reader.BaseStream, "Load, Begin, LayerInfo"); // Some keys use a signature of 8B64, but the identity of these keys // is undocumented. We will therefore accept either signature. var signature = reader.ReadAsciiChars(4); if ((signature != "8BIM") && (signature != "8B64")) { throw new PsdInvalidException( "LayerInfo signature invalid, must be 8BIM or 8B64."); } var key = reader.ReadAsciiChars(4); var hasLongLength = LayerInfoUtil.HasLongLength(key, psdFile.IsLargeDocument); LayerInfo result = new RawLayerInfo("dummy"); bool breakFromLoop = false; while (!breakFromLoop) { var baseStartPosition = reader.BaseStream.Position; var length = hasLongLength ? reader.ReadInt64() : reader.ReadInt32(); var startPosition = reader.BaseStream.Position; switch (key) { case "Layr": case "Lr16": case "Lr32": result = new InfoLayers(reader, psdFile, key, length); break; case "lsct": case "lsdk": result = new LayerSectionInfo(reader, key, (int)length); break; case "luni": result = new LayerUnicodeName(reader); break; case "lyid": result = new LayerId(reader, key, length); break; default: result = new RawLayerInfo(reader, signature, key, length); break; } // May have additional padding applied. var endPosition = startPosition + length; if (reader.BaseStream.Position < endPosition) { reader.BaseStream.Position = endPosition; } // Documentation states that the length is even-padded. Actually: // 1. Most keys have 4-padded lengths. // 2. However, some keys (LMsk) have even-padded lengths. // 3. Other keys (Txt2, Lr16, Lr32) have unpadded lengths. // // Photoshop writes data that is always 4-padded, even when the stated // length is not a multiple of 4. The length mismatch seems to occur // only on global layer info. We do not read extra padding in other // cases because third-party programs are likely to follow the spec. if (globalLayerInfo) { reader.ReadPadding(startPosition, 4); } //try if we can read the next signature if (reader.BaseStream.Position < fileEndPos) { var nowPosition = reader.BaseStream.Position; signature = reader.ReadAsciiChars(4); if ((signature != "8BIM") && (signature != "8B64")) { hasLongLength = true; reader.BaseStream.Position = baseStartPosition; } else { reader.BaseStream.Position = nowPosition; breakFromLoop = true; } } else { breakFromLoop = true; } } Util.DebugMessage(reader.BaseStream, "Load, End, LayerInfo, {0}, {1}", result.Signature, result.Key); return(result); }
/// <summary> /// Loads the next LayerInfo record. /// </summary> /// <param name="reader">The file reader</param> /// <param name="psdFile">The PSD file.</param> /// <param name="globalLayerInfo">True if the LayerInfo record is being /// loaded from the end of the Layer and Mask Information section; /// false if it is being loaded from the end of a Layer record.</param> /// <returns>LayerInfo object if it was successfully read, or null if /// padding was found.</returns> private static LayerInfo Load(PsdBinaryReader reader, PsdFile psdFile, bool globalLayerInfo) { Util.DebugMessage(reader.BaseStream, "Load, Begin, LayerInfo"); // Most keys have undocumented signatures, so we always accept either one. var signature = reader.ReadAsciiChars(4); if ((signature != "8BIM") && (signature != "8B64")) { throw new PsdInvalidException( $"{nameof(LayerInfo)} signature invalid, must be 8BIM or 8B64."); } var key = reader.ReadAsciiChars(4); var hasLongLength = LayerInfoUtil.HasLongLength(signature, key, psdFile.IsLargeDocument); var length = hasLongLength ? reader.ReadInt64() : reader.ReadInt32(); var startPosition = reader.BaseStream.Position; LayerInfo result; switch (key) { case "Layr": case "Lr16": case "Lr32": result = new InfoLayers(reader, psdFile, key, length); break; case "lsct": case "lsdk": result = new LayerSectionInfo(reader, key, (int)length); break; case "luni": result = new LayerUnicodeName(reader); break; default: result = new RawLayerInfo(reader, signature, key, length); break; } // May have additional padding applied. var endPosition = startPosition + length; if (reader.BaseStream.Position < endPosition) { reader.BaseStream.Position = endPosition; } // Documentation states that the length is even-padded. Actually: // 1. Most keys have 4-padded lengths. // 2. However, some keys (LMsk) have even-padded lengths. // 3. Other keys (Txt2, Lr16, Lr32) have unpadded lengths. // // Photoshop writes data that is always 4-padded, even when the stated // length is not a multiple of 4. The length mismatch seems to occur // only on global layer info. We do not read extra padding in other // cases because third-party programs are likely to follow the spec. if (globalLayerInfo) { reader.ReadPadding(startPosition, 4); } Util.DebugMessage(reader.BaseStream, $"Load, End, LayerInfo, {result.Signature}, {result.Key}"); return(result); }