Beispiel #1
0
 public VersionInfo(PsdBinaryReader reader, string name)
     : base(name)
 {
     Version           = reader.ReadUInt32();
     HasRealMergedData = reader.ReadBoolean();
     ReaderName        = reader.ReadUnicodeString();
     WriterName        = reader.ReadUnicodeString();
     FileVersion       = reader.ReadUInt32();
 }
Beispiel #2
0
        public ResolutionInfo(PsdBinaryReader reader, string name)
            : base(name)
        {
            this.HDpi             = new UFixed1616(reader.ReadUInt32());
            this.HResDisplayUnit  = (ResUnit)reader.ReadInt16();
            this.WidthDisplayUnit = (Unit)reader.ReadInt16();

            this.VDpi              = new UFixed1616(reader.ReadUInt32());
            this.VResDisplayUnit   = (ResUnit)reader.ReadInt16();
            this.HeightDisplayUnit = (Unit)reader.ReadInt16();
        }
Beispiel #3
0
        ///////////////////////////////////////////////////////////////////////////

        private void LoadImageResources(PsdBinaryReader reader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, ImageResources");

            var imageResourcesLength = reader.ReadUInt32();

            if (imageResourcesLength <= 0)
            {
                return;
            }

            var startPosition = reader.BaseStream.Position;
            var endPosition   = startPosition + imageResourcesLength;

            while (reader.BaseStream.Position < endPosition)
            {
                var imageResource = ImageResourceFactory.CreateImageResource(reader);
                ImageResources.Add(imageResource);
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, ImageResources");

            //-----------------------------------------------------------------------
            // make sure we are not on a wrong offset, so set the stream position
            // manually
            reader.BaseStream.Position = startPosition + imageResourcesLength;
        }
Beispiel #4
0
        public static ImageResource CreateImageResource(PsdBinaryReader reader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, ImageResource");

            var signature     = reader.ReadAsciiChars(4);
            var resourceIdInt = reader.ReadUInt16();
            var name          = reader.ReadPascalString(2);
            var dataLength    = (int)reader.ReadUInt32();

            var dataPaddedLength = Util.RoundUp(dataLength, 2);
            var endPosition      = reader.BaseStream.Position + dataPaddedLength;

            ImageResource resource   = null;
            var           resourceId = (ResourceID)resourceIdInt;

            switch (resourceId)
            {
            case ResourceID.ResolutionInfo:
                resource = new ResolutionInfo(reader, name);
                break;

            case ResourceID.AlphaChannelNames:
                resource = new AlphaChannelNames(reader, name, dataLength);
                break;

            case ResourceID.UnicodeAlphaNames:
                resource = new UnicodeAlphaNames(reader, name, dataLength);
                break;

            case ResourceID.VersionInfo:
                resource = new VersionInfo(reader, name);
                break;

            default:
                resource = new RawImageResource(reader, signature, resourceId, name, dataLength);
                break;
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, ImageResource, {0}",
                              resourceId);

            // Reposition the reader if we do not consume the full resource block.
            // This takes care of the even-padding, and also preserves forward-
            // compatibility in case a resource block is later extended with
            // additional properties.
            if (reader.BaseStream.Position < endPosition)
            {
                reader.BaseStream.Position = endPosition;
            }

            // However, overruns are definitely an error.
            if (reader.BaseStream.Position > endPosition)
            {
                throw new PsdInvalidException("Corruption detected in resource.");
            }

            return(resource);
        }
Beispiel #5
0
        private void LoadColorModeData(PsdBinaryReader reader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, ColorModeData");

            var paletteLength = reader.ReadUInt32();

            if (paletteLength > 0)
            {
                ColorModeData = reader.ReadBytes((int)paletteLength);
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, ColorModeData");
        }
Beispiel #6
0
        ///////////////////////////////////////////////////////////////////////////

        private void LoadLayerAndMaskInfo(PsdBinaryReader reader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, Layer and mask info");

            var layersAndMaskLength = IsLargeDocument
                ? reader.ReadInt64()
                : reader.ReadUInt32();

            if (layersAndMaskLength <= 0)
            {
                return;
            }

            var startPosition = reader.BaseStream.Position;
            var endPosition   = startPosition + layersAndMaskLength;

            LoadLayers(reader, true);
            LoadGlobalLayerMask(reader);

            //-----------------------------------------------------------------------
            // Load Additional Layer Information

            while (reader.BaseStream.Position < endPosition)
            {
                var info = LayerInfoFactory.Load(reader,
                                                 psdFile: this,
                                                 globalLayerInfo: true);
                AdditionalInfo.Add(info);

                if (info is RawLayerInfo)
                {
                    var layerInfo = (RawLayerInfo)info;
                    switch (info.Key)
                    {
                    case "LMsk":
                        _globalLayerMaskData = layerInfo.Data;
                        break;
                    }
                }
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, Layer and mask info");

            //-----------------------------------------------------------------------
            // make sure we are not on a wrong offset, so set the stream position
            // manually
            reader.BaseStream.Position = startPosition + layersAndMaskLength;
        }
Beispiel #7
0
        private void LoadGlobalLayerMask(PsdBinaryReader reader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, GlobalLayerMask");

            var maskLength = reader.ReadUInt32();

            if (maskLength <= 0)
            {
                Util.DebugMessage(reader.BaseStream, "Load, End, GlobalLayerMask");
                return;
            }

            _globalLayerMaskData = reader.ReadBytes((int)maskLength);

            Util.DebugMessage(reader.BaseStream, "Load, End, GlobalLayerMask");
        }
Beispiel #8
0
        public MaskInfo(PsdBinaryReader reader, Layer layer)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, MaskInfo");

            var maskLength = reader.ReadUInt32();

            if (maskLength <= 0)
            {
                return;
            }

            var startPosition = reader.BaseStream.Position;
            var endPosition   = startPosition + maskLength;

            // Read layer mask
            var rectangle       = reader.ReadRectangle();
            var backgroundColor = reader.ReadByte();
            var flagsByte       = reader.ReadByte();

            LayerMask = new Mask(layer, rectangle, backgroundColor, new BitVector32(flagsByte));

            // User mask is supplied separately when there is also a vector mask.
            if (maskLength == 36)
            {
                var userFlagsByte       = reader.ReadByte();
                var userBackgroundColor = reader.ReadByte();
                var userRectangle       = reader.ReadRectangle();
                UserMask = new Mask(layer, userRectangle, userBackgroundColor,
                                    new BitVector32(userFlagsByte));
            }

            // 20-byte mask data will end with padding.
            reader.BaseStream.Position = endPosition;

            Util.DebugMessage(reader.BaseStream, "Load, End, MaskInfo");
        }
Beispiel #9
0
        ///////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Load Layers Info section, including image data.
        /// </summary>
        /// <param name="reader">PSD reader.</param>
        /// <param name="hasHeader">Whether the Layers Info section has a length header.</param>
        internal void LoadLayers(PsdBinaryReader reader, bool hasHeader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, Layers Info section");

            long sectionLength = 0;

            if (hasHeader)
            {
                sectionLength = IsLargeDocument
                    ? reader.ReadInt64()
                    : reader.ReadUInt32();

                if (sectionLength <= 0)
                {
                    // The callback may take action when there are 0 layers, so it must
                    // be called even though the Layers Info section is empty.
                    LoadContext.OnLoadLayersHeader(this);
                    Util.DebugMessage(reader.BaseStream, "Load, End, Layers Info section");
                    return;
                }
            }

            var startPosition = reader.BaseStream.Position;
            var numLayers     = reader.ReadInt16();

            // If numLayers < 0, then number of layers is absolute value,
            // and the first alpha channel contains the transparency data for
            // the merged result.
            if (numLayers < 0)
            {
                AbsoluteAlpha = true;
                numLayers     = Math.Abs(numLayers);
            }

            for (int i = 0; i < numLayers; i++)
            {
                var layer = new Layer(reader, this);
                Layers.Add(layer);
            }

            // Header is complete just before loading pixel data
            LoadContext.OnLoadLayersHeader(this);

            //-----------------------------------------------------------------------

            // Load image data for all channels.
            foreach (var layer in Layers)
            {
                Util.DebugMessage(reader.BaseStream,
                                  $"Load, Begin, Layer image, {layer.Name}");
                foreach (var channel in layer.Channels)
                {
                    channel.LoadPixelData(reader);
                }
                Util.DebugMessage(reader.BaseStream,
                                  $"Load, End, Layer image, {layer.Name}");
            }

            // Length is set to 0 when called on higher bitdepth layers.
            if (sectionLength > 0)
            {
                // Layers Info section is documented to be even-padded, but Photoshop
                // actually pads to 4 bytes.
                var endPosition    = startPosition + sectionLength;
                var positionOffset = reader.BaseStream.Position - endPosition;
                Debug.Assert(positionOffset > -4,
                             "LoadLayers did not read the full length of the Layers Info section.");
                Debug.Assert(positionOffset <= 0,
                             "LoadLayers read past the end of the Layers Info section.");


                if (reader.BaseStream.Position < endPosition)
                {
                    reader.BaseStream.Position = endPosition;
                }
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, Layers");
        }
Beispiel #10
0
        public Layer(PsdBinaryReader reader, PsdFile psdFile)
            : this(psdFile)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, Layer");

            Rect = reader.ReadRectangle();

            //-----------------------------------------------------------------------
            // Read channel headers.  Image data comes later, after the layer header.

            Int32 numberOfChannels = reader.ReadUInt16();
            for (Int32 channel = 0; channel < numberOfChannels; channel++)
            {
                var ch = new Channel(reader, this);
                Channels.Add(ch);
            }

            //-----------------------------------------------------------------------
            //

            var signature = reader.ReadAsciiChars(4);
            if (signature != "8BIM")
            {
                throw (new PsdInvalidException("Invalid signature in layer header."));
            }

            BlendModeKey = reader.ReadAsciiChars(4);
            Opacity      = reader.ReadByte();
            Clipping     = reader.ReadBoolean();

            var flagsByte = reader.ReadByte();
            _flags = new BitVector32(flagsByte);
            reader.ReadByte(); //padding

            //-----------------------------------------------------------------------

            // This is the total size of the MaskData, the BlendingRangesData, the
            // Name and the AdjustmentLayerInfo.
            var extraDataSize          = reader.ReadUInt32();
            var extraDataStartPosition = reader.BaseStream.Position;

            Masks = new MaskInfo(reader, this);
            BlendingRangesData = new BlendingRanges(reader, this);
            Name = reader.ReadPascalString(4);

            //-----------------------------------------------------------------------
            // Process Additional Layer Information

            Int64 adjustmentLayerEndPos = extraDataStartPosition + extraDataSize;
            while (reader.BaseStream.Position < adjustmentLayerEndPos)
            {
                var layerInfo = LayerInfoFactory.Load(reader,
                                                      psdFile: PsdFile,
                                                      globalLayerInfo: false);
                AdditionalInfo.Add(layerInfo);
            }

            foreach (var adjustmentInfo in AdditionalInfo)
            {
                switch (adjustmentInfo.Key)
                {
                case "luni":
                    Name = ((LayerUnicodeName)adjustmentInfo).Name;
                    break;
                }
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, Layer, {0}", Name);

            PsdFile.LoadContext.OnLoadLayerHeader(this);
        }