| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /////////////////////////////////////////////////////////////////////////////////
- //
- // 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-2016 Tao Yue
- //
- // See LICENSE.txt for complete licensing and attribution information.
- //
- /////////////////////////////////////////////////////////////////////////////////
- using System;
- using System.Diagnostics;
- using System.IO;
- namespace PhotoshopFile
- {
- internal static class LayerInfoFactory
- {
- /// <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;
- }
- }
- internal static class LayerInfoUtil
- {
- internal static bool HasLongLength(string key, bool isLargeDocument)
- {
- if (!isLargeDocument)
- {
- return false;
- }
- //return false;
- switch (key)
- {
- case "LMsk":
- case "Lr16":
- case "Lr32":
- case "Layr":
- case "Mt16":
- case "Mt32":
- case "Mtrn":
- case "Alph":
- case "FMsk":
- case "lnk2":
- case "FEid":
- case "FXid":
- case "PxSD":
- case "lnkE": // Undocumented
- case "extn": // Undocumented
- case "cinf": // Undocumented
- return true;
- default:
- return false;
- }
- }
- }
- internal abstract class LayerInfo
- {
- public abstract string Signature { get; }
- public abstract string Key { get; }
- }
- }
|