Пример #1
0
        /// <summary>
        /// Reads the scanlines within the image.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="dataStream">The <see cref="MemoryStream"/> containing data.</param>
        /// <param name="pixels"> The pixel data.</param>
        private void ReadScanlines <TColor, TPacked>(MemoryStream dataStream, PixelAccessor <TColor, TPacked> pixels)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            this.bytesPerPixel    = this.CalculateBytesPerPixel();
            this.bytesPerScanline = this.CalculateScanlineLength() + 1;
            this.bytesPerSample   = 1;
            if (this.header.BitDepth >= 8)
            {
                this.bytesPerSample = this.header.BitDepth / 8;
            }

            dataStream.Position = 0;
            using (ZlibInflateStream compressedStream = new ZlibInflateStream(dataStream))
            {
                using (MemoryStream decompressedStream = new MemoryStream())
                {
                    compressedStream.CopyTo(decompressedStream);
                    decompressedStream.Flush();
                    decompressedStream.Position = 0;
                    this.DecodePixelData(decompressedStream, pixels);
                    //byte[] decompressedBytes = decompressedStream.ToArray();
                    //this.DecodePixelData(decompressedBytes, pixels);
                }

                //byte[] decompressedBytes = compressedStream.ToArray();
                //this.DecodePixelData(decompressedBytes, pixels);
            }
        }
Пример #2
0
        /// <summary>
        /// Reads the scanlines within the image.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="dataStream">The <see cref="MemoryStream"/> containing data.</param>
        /// <param name="pixels"> The pixel data.</param>
        private void ReadScanlines <TColor, TPacked>(MemoryStream dataStream, PixelAccessor <TColor, TPacked> pixels)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct, IEquatable <TPacked>
        {
            this.bytesPerPixel    = this.CalculateBytesPerPixel();
            this.bytesPerScanline = this.CalculateScanlineLength(this.header.Width) + 1;
            this.bytesPerSample   = 1;
            if (this.header.BitDepth >= 8)
            {
                this.bytesPerSample = this.header.BitDepth / 8;
            }

            dataStream.Position = 0;
            using (ZlibInflateStream compressedStream = new ZlibInflateStream(dataStream))
            {
                if (this.header.InterlaceMethod == PngInterlaceMode.Adam7)
                {
                    this.DecodeInterlacedPixelData(compressedStream, pixels);
                }
                else
                {
                    this.DecodePixelData(compressedStream, pixels);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Decodes the stream to the image.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="stream">The stream containing image data. </param>
        /// <exception cref="ImageFormatException">
        /// Thrown if the stream does not contain and end chunk.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown if the image is larger than the maximum allowable size.
        /// </exception>
        /// <returns>The decoded image</returns>
        public Image <TPixel> Decode <TPixel>(Stream stream)
            where TPixel : struct, IPixel <TPixel>
        {
            var metadata = new ImageMetaData();

            this.currentStream = stream;
            this.currentStream.Skip(8);
            Image <TPixel> image = null;

            try
            {
                using (var deframeStream = new ZlibInflateStream(this.currentStream))
                {
                    PngChunk currentChunk;
                    while (!this.isEndChunkReached && (currentChunk = this.ReadChunk()) != null)
                    {
                        try
                        {
                            switch (currentChunk.Type)
                            {
                            case PngChunkTypes.Header:
                                this.ReadHeaderChunk(currentChunk.Data);
                                this.ValidateHeader();
                                break;

                            case PngChunkTypes.Physical:
                                this.ReadPhysicalChunk(metadata, currentChunk.Data);
                                break;

                            case PngChunkTypes.Data:
                                if (image == null)
                                {
                                    this.InitializeImage(metadata, out image);
                                }

                                deframeStream.AllocateNewBytes(currentChunk.Length);
                                this.ReadScanlines(deframeStream.CompressedStream, image);
                                stream.Read(this.crcBuffer, 0, 4);
                                break;

                            case PngChunkTypes.Palette:
                                byte[] pal = new byte[currentChunk.Length];
                                Buffer.BlockCopy(currentChunk.Data, 0, pal, 0, currentChunk.Length);
                                this.palette = pal;
                                break;

                            case PngChunkTypes.PaletteAlpha:
                                byte[] alpha = new byte[currentChunk.Length];
                                Buffer.BlockCopy(currentChunk.Data, 0, alpha, 0, currentChunk.Length);
                                this.paletteAlpha = alpha;
                                break;

                            case PngChunkTypes.Text:
                                this.ReadTextChunk(metadata, currentChunk.Data, currentChunk.Length);
                                break;

                            case PngChunkTypes.End:
                                this.isEndChunkReached = true;
                                break;
                            }
                        }
                        finally
                        {
                            // Data is rented in ReadChunkData()
                            if (currentChunk.Data != null)
                            {
                                ArrayPool <byte> .Shared.Return(currentChunk.Data);
                            }
                        }
                    }
                }

                return(image);
            }
            finally
            {
                this.scanline?.Dispose();
                this.previousScanline?.Dispose();
            }
        }