Пример #1
0
        private void LoadPSPFile(Stream input)
        {
            byte[] sigBytes = new byte[32];

            input.ProperRead(sigBytes, 0, sigBytes.Length);

            if (!CheckSig(sigBytes))
            {
                throw new FormatException(Properties.Resources.InvalidPSPFile);
            }

            using (BufferedBinaryReader reader = new BufferedBinaryReader(input))
            {
                this.fileHeader = new FileHeader(reader);

                while (reader.Position < reader.Length)
                {
                    uint blockSig = reader.ReadUInt32();
                    if (blockSig != PSPConstants.blockIdentifier)
                    {
                        throw new FormatException(Properties.Resources.InvalidBlockSignature);
                    }
                    PSPBlockID blockID            = (PSPBlockID)reader.ReadUInt16();
                    uint       initialBlockLength = this.fileHeader.Major <= PSPConstants.majorVersion5 ? reader.ReadUInt32() : 0;
                    uint       blockLength        = reader.ReadUInt32();

                    switch (blockID)
                    {
                    case PSPBlockID.ImageAttributes:
                        this.imageAttributes = new GeneralImageAttributes(reader, this.fileHeader.Major);
                        break;

                    case PSPBlockID.Creator:
                        this.creator = new CreatorBlock(reader, blockLength);
                        break;

                    case PSPBlockID.ColorPalette:
                        this.globalPalette = new ColorPaletteBlock(reader, this.fileHeader.Major);
                        break;

                    case PSPBlockID.LayerStart:
                        this.layerBlock = new LayerBlock(reader, this.imageAttributes, this.fileHeader.Major);
                        break;

                    case PSPBlockID.ExtendedData:
                        this.extData = new ExtendedDataBlock(reader, blockLength);
                        break;

#if DEBUG
                    case PSPBlockID.CompositeImageBank:
                        this.compImage = new CompositeImageBlock(reader, this.fileHeader.Major);
                        break;
#endif
                    default:
                        reader.Position += blockLength;
                        break;
                    }
                }
            }
        }
Пример #2
0
 /// <summary>
 /// Checks that the block type matches the expected <see cref="PSPBlockID"/>.
 /// </summary>
 /// <param name="blockID">The block identifier.</param>
 /// <param name="expected">The expected <see cref="PSPBlockID"/>.</param>
 internal static void CheckBlockType(ushort blockID, PSPBlockID expected)
 {
     if (blockID != (ushort)expected)
     {
         throw new FormatException(string.Format(Properties.Resources.UnexpectedBlockTypeFormat,
             blockID.ToString(CultureInfo.InvariantCulture),
             ((ushort)expected).ToString(CultureInfo.InvariantCulture),
             expected.ToString()));
     }
 }
Пример #3
0
        public CompositeImageInfoChunk(BufferedBinaryReader br, CompositeImageAttributesChunk attr, ushort majorVersion)
        {
            this.chunkSize       = br.ReadUInt32();
            this.bitmapCount     = br.ReadUInt16();
            this.channelCount    = br.ReadUInt16();
            this.paletteSubBlock = null;
            this.channelBlocks   = new ChannelSubBlock[this.channelCount];

            long dif = (long)this.chunkSize - HeaderSize;

            if (dif > 0)
            {
                br.Position += dif;
            }

            int index = 0;

            do
            {
                uint blockSig = br.ReadUInt32();
                if (blockSig != PSPConstants.blockIdentifier)
                {
                    throw new FormatException(Properties.Resources.InvalidBlockSignature);
                }
                PSPBlockID blockType = (PSPBlockID)br.ReadUInt16();
#pragma warning disable IDE0059 // Value assigned to symbol is never used
                uint chunkLength = br.ReadUInt32();
#pragma warning restore IDE0059 // Value assigned to symbol is never used

                switch (blockType)
                {
                case PSPBlockID.ColorPalette:
                    this.paletteSubBlock = new ColorPaletteBlock(br, majorVersion);
                    break;

                case PSPBlockID.Channel:
                    ChannelSubBlock block = new ChannelSubBlock(br, attr.compressionType, majorVersion);
                    this.channelBlocks[index] = block;
                    index++;
                    break;
                }
            }while (index < this.channelCount);
        }
Пример #4
0
        public ThumbnailBlock(BufferedBinaryReader br)
        {
            this.width             = br.ReadInt32();
            this.height            = br.ReadInt32();
            this.bitDepth          = br.ReadUInt16();
            this.compressionType   = (PSPCompression)br.ReadUInt16();
            this.planeCount        = br.ReadUInt16();
            this.colorCount        = br.ReadUInt32();
            this.paletteEntryCount = br.ReadUInt32();
            this.channelCount      = br.ReadUInt16();

            this.channelBlocks = new ChannelSubBlock[this.channelCount];

            int index = 0;

            do
            {
                uint blockSig = br.ReadUInt32();
                if (blockSig != PSPConstants.blockIdentifier)
                {
                    throw new System.FormatException(Properties.Resources.InvalidBlockSignature);
                }
                PSPBlockID blockType = (PSPBlockID)br.ReadUInt16();
#pragma warning disable IDE0059 // Value assigned to symbol is never used
                uint chunkLength = br.ReadUInt32();
#pragma warning restore IDE0059 // Value assigned to symbol is never used

                switch (blockType)
                {
                case PSPBlockID.ColorPalette:
                    this.paletteSubBlock = new ColorPaletteBlock(br, PSPConstants.majorVersion5);
                    break;

                case PSPBlockID.Channel:
                    ChannelSubBlock block = new ChannelSubBlock(br, this.compressionType, PSPConstants.majorVersion5);
                    this.channelBlocks[index] = block;
                    index++;
                    break;
                }
            }while (index < this.channelCount);
        }
Пример #5
0
        private static IList <RasterLayerChunk> CountRasterChunks(BufferedBinaryReader reader, int layerCount, ushort majorVersion)
        {
            List <RasterLayerChunk> rasterChunks = new List <RasterLayerChunk>(layerCount);

            int index = 0;

            while (index < layerCount)
            {
                uint head = reader.ReadUInt32();
                if (head != PSPConstants.blockIdentifier)
                {
                    throw new FormatException(Properties.Resources.InvalidBlockSignature);
                }
                PSPBlockID blockID = (PSPBlockID)reader.ReadUInt16();
#pragma warning disable IDE0059 // Value assigned to symbol is never used
                uint initialBlockLength = majorVersion <= PSPConstants.majorVersion5 ? reader.ReadUInt32() : 0;
#pragma warning restore IDE0059 // Value assigned to symbol is never used
                uint blockLength = reader.ReadUInt32();

                if (blockID == PSPBlockID.Layer)
                {
                    index++;
                    long endOffset = reader.Position + blockLength;

                    LayerInfoChunk chunk         = new LayerInfoChunk(reader, majorVersion);
                    long           currentOffset = reader.Position;

                    switch (chunk.type)
                    {
                    case PSPLayerType.Raster:
                    case PSPLayerType.FloatingRasterSelection:
                        if (majorVersion >= PSPConstants.majorVersion12)
                        {
                            // Paint Shop Pro X2 and later insert an unknown block (0x21) before the start of the LayerBitmapInfo chunk.
                            bool ok = false;
                            if (reader.ReadUInt32() == PSPConstants.blockIdentifier)
                            {
                                ushort block  = reader.ReadUInt16();
                                uint   length = reader.ReadUInt32();

                                if (block == 0x21)
                                {
                                    reader.Position += length;
                                    if (reader.ReadUInt32() == LayerBitmapInfoChunk.HeaderSize)
                                    {
                                        reader.Position -= 4L;
                                        currentOffset    = reader.Position;
                                        ok = true;
                                    }
                                }
                            }

                            if (!ok)
                            {
                                throw new FormatException(Properties.Resources.UnsupportedFormatVersion);
                            }
                        }

                        rasterChunks.Add(new RasterLayerChunk(chunk, currentOffset));
                        break;
                    }

                    reader.Position += (endOffset - currentOffset);
                }
                else
                {
                    reader.Position += blockLength;
                }
            }

            return(rasterChunks);
        }
Пример #6
0
        public CompositeImageBlock(BufferedBinaryReader br, ushort majorVersion)
        {
            this.blockSize      = br.ReadUInt32();
            this.attrChunkCount = br.ReadUInt32();

            long dif = (long)this.blockSize - HeaderSize;

            if (dif > 0)
            {
                br.Position += dif;
            }

            this.attrChunks = new CompositeImageAttributesChunk[(int)this.attrChunkCount];

            for (int i = 0; i < this.attrChunkCount; i++)
            {
                uint blockSig = br.ReadUInt32();
                if (blockSig != PSPConstants.blockIdentifier)
                {
                    throw new FormatException(Properties.Resources.InvalidBlockSignature);
                }
                ushort blockType = br.ReadUInt16();
                PSPUtil.CheckBlockType(blockType, PSPBlockID.CompositeImageAttributes);
#pragma warning disable IDE0059 // Value assigned to symbol is never used
                uint attrChunkLength = br.ReadUInt32();
#pragma warning restore IDE0059 // Value assigned to symbol is never used

                this.attrChunks[i] = new CompositeImageAttributesChunk(br);
            }

            for (int i = 0; i < this.attrChunkCount; i++)
            {
                uint blockSig = br.ReadUInt32();
                if (blockSig != PSPConstants.blockIdentifier)
                {
                    throw new FormatException(Properties.Resources.InvalidBlockSignature);
                }
                PSPBlockID blockType = (PSPBlockID)br.ReadUInt16();
#pragma warning disable IDE0059 // Value assigned to symbol is never used
                uint chunkLength = br.ReadUInt32();
#pragma warning restore IDE0059 // Value assigned to symbol is never used

                switch (blockType)
                {
                case PSPBlockID.CompositeImage:
                    this.imageChunk = new CompositeImageInfoChunk(br, this.attrChunks[i], majorVersion);
                    break;

                case PSPBlockID.JPEGImage:
                    this.jpegChunk = new JPEGCompositeInfoChunk(br);
                    break;
                }
            }

            if (this.jpegChunk.imageData != null)
            {
                using (MemoryStream ms = new MemoryStream(this.jpegChunk.imageData))
                {
                    using (System.Drawing.Bitmap th = new System.Drawing.Bitmap(ms))
                    {
                        Debug.WriteLine(string.Format("JPEG thumbnail size: {0}x{1}", th.Width, th.Height));
                    }
                }
            }
        }