예제 #1
0
        public List <AdditionalLayerInformationBlock> Read(Stream stream, AdditionalLayerInformation additionalLayerInformation, FileVersion fileVersion)
        {
            var reader = new BigEndianBinaryReader(stream);

            stream.Position = additionalLayerInformation.Offset;
            var list = new List <AdditionalLayerInformationBlock>();

            while (stream.Position < additionalLayerInformation.Offset + additionalLayerInformation.Length)
            {
                var block = new AdditionalLayerInformationBlock();
                block.Signature = new string(reader.ReadChars(4));
                block.Key       = new string(reader.ReadChars(4));

                if (fileVersion == FileVersion.Psb && LongDataKeys.Contains(block.Key))
                {
                    block.Length = reader.ReadInt64();
                }
                else
                {
                    block.Length = reader.ReadInt32();
                }

                if ((block.Length % 2) != 0)
                {
                    block.Length += 3; // should be 1, but 3 works there for unknown reason
                }

                block.Offset     = stream.Position;
                stream.Position += block.Length;
                list.Add(block);
            }

            return(list);
        }
예제 #2
0
        public static LayerElement Parse(string filePath)
        {
            var layerElements = new List <LayerElement>();

            try
            {
                using (var fs = new FileStream($@"{filePath}", FileMode.Open, FileAccess.Read))
                {
                    /*
                     * File Header Section
                     */

                    // Signature
                    Util.ReadString(out var fileSignature, fs, 4, Encoding.UTF8);
                    if (fileSignature != "8BPS")
                    {
                        return(new LayerElement());
                    }

                    // Version
                    Util.ReadInt16(out var version, fs, 2);
                    if (version != 1)
                    {
                        return(new LayerElement());
                    }

                    // Skip the rest
                    fs.Seek(20, SeekOrigin.Current);


                    /*
                     * Color Mode Data Section
                     */

                    // Length
                    Util.ReadInt32(out var colorModeLength, fs, 4);
                    if (colorModeLength > 0)
                    {
                        // Skip the rest
                        fs.Seek(colorModeLength, SeekOrigin.Current);
                    }


                    /*
                     * Image Resources Section
                     */

                    Util.ReadInt32(out var imgResLength, fs, 4);
                    if (imgResLength > 0)
                    {
                        // Skip the rest
                        fs.Seek(imgResLength, SeekOrigin.Current);
                    }


                    /*
                     * Layer and Mask Information Section
                     */

                    // Length (Skip)
                    fs.Seek(4, SeekOrigin.Current);

                    // Layer info
                    // Layer info -> Length
                    fs.Seek(4, SeekOrigin.Current);
                    //ReadInt32(out var layerInfoLength, fs, 4);

                    // Layer info -> Layer count
                    Util.ReadInt16(out var layerCount, fs, 2);
                    layerCount = Math.Abs(layerCount);

                    // Layer records
                    for (var i = 0; i < layerCount; i++)
                    {
                        // Layer record -> Rectangle (Skip)
                        fs.Seek(16, SeekOrigin.Current);

                        // Layer record -> Number of channels
                        Util.ReadInt16(out var channelCount, fs, 2);

                        // Skip channel info, blend mode signature, blend mode key, opacity, clipping, flags, filler
                        fs.Seek(6 * channelCount + 12, SeekOrigin.Current);

                        // Layer record -> Length of the extra data field
                        Util.ReadInt32(out var extraDataLength, fs, 4);

                        // Layer record -> Layer mask data
                        // Layer record -> Layer mask data -> Length
                        Util.ReadInt32(out var maskDataLength, fs, 4);
                        if (maskDataLength > 0)
                        {
                            // Skip the rest
                            fs.Seek(maskDataLength, SeekOrigin.Current);

                            extraDataLength -= maskDataLength;
                        }

                        extraDataLength -= 4;

                        // Layer record -> Layer blending ranges data
                        // Layer record -> Layer blending ranges data -> Length
                        Util.ReadInt32(out var blendingRangesDataLength, fs, 4);
                        if (blendingRangesDataLength > 0)
                        {
                            // Skip the rest
                            fs.Seek(blendingRangesDataLength, SeekOrigin.Current);

                            extraDataLength -= blendingRangesDataLength;
                        }

                        extraDataLength -= 4;

                        // Layer record -> Layer name
                        // NOTE: Pascal string, padded to a multiple of 4 bytes.
                        Util.ReadShort(out var layerNameCount, fs, 1);

                        //Skip UTF8 layer name
                        fs.Seek(layerNameCount, SeekOrigin.Current);

                        extraDataLength -= layerNameCount + 1;

                        var remainder = (layerNameCount + 1) % 4;
                        if (remainder > 0)
                        {
                            var paddedCount = 4 - remainder;

                            // Skip padded data
                            fs.Seek(paddedCount, SeekOrigin.Current);

                            extraDataLength -= paddedCount;
                        }

                        // Additional Layer Information
                        Util.ReadByte(out var layerInfoBytes, fs, extraDataLength, false);

                        var layerInfo = AdditionalLayerInformation.BuildFromByte(layerInfoBytes);

                        layerElements.Add(new LayerElement()
                        {
                            Name    = layerInfo.UnicodeName,
                            IsGroup = layerInfo.Type == AdditionalLayerInformation.LayerSectionType.OpenFolder ||
                                      layerInfo.Type == AdditionalLayerInformation.LayerSectionType.ClosedFolder,
                            IsSectionDivider = layerInfo.Type == AdditionalLayerInformation.LayerSectionType.BoundingSectionDivider
                        });
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return(new LayerElement());
            }

            layerElements.Reverse();

            // Build layer tree and return it
            return(BuildLayerTree(layerElements.ToArray()));
        }