Пример #1
0
        /// <summary>
        /// Reads the raw image information from the specified stream.
        /// </summary>
        /// <param name="stream">The <see cref="Stream"/> containing image data.</param>
        public IImageInfo Identify(Stream stream)
        {
            var         metadata    = new ImageMetadata();
            PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance);

            this.currentStream = stream;
            this.currentStream.Skip(8);
            try
            {
                while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
                {
                    try
                    {
                        switch (chunk.Type)
                        {
                        case PngChunkType.Header:
                            this.ReadHeaderChunk(pngMetadata, chunk.Data.Array);
                            break;

                        case PngChunkType.Physical:
                            this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan());
                            break;

                        case PngChunkType.Gamma:
                            this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan());
                            break;

                        case PngChunkType.Data:
                            this.SkipChunkDataAndCrc(chunk);
                            break;

                        case PngChunkType.Text:
                            this.ReadTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.End:
                            this.isEndChunkReached = true;
                            break;
                        }
                    }
                    finally
                    {
                        chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
                    }
                }
            }
            finally
            {
                this.scanline?.Dispose();
                this.previousScanline?.Dispose();
            }

            if (this.header.Width == 0 && this.header.Height == 0)
            {
                PngThrowHelper.ThrowNoHeader();
            }

            return(new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata));
        }
Пример #2
0
        /// <summary>
        /// Decodes the image from the specified stream to the <see cref="ImageFrame{TPixel}"/>.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="configuration">The configuration for the image.</param>
        /// <param name="stream">The <see cref="Stream"/> containing image data.</param>
        /// <returns>The decoded image.</returns>
        public Image <TPixel> Decode <TPixel>(Configuration configuration, Stream stream)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            var decoder = new PngDecoderCore(configuration, this);

            try
            {
                return(decoder.Decode <TPixel>(stream));
            }
            catch (InvalidMemoryOperationException ex)
            {
                Size dims = decoder.Dimensions;

                PngThrowHelper.ThrowInvalidImageContentException($"Can not decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}.", ex);

                // Not reachable, as the previous statement will throw a exception.
                return(null);
            }
        }
Пример #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();
            PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance);

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

            try
            {
                while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
                {
                    try
                    {
                        switch (chunk.Type)
                        {
                        case PngChunkType.Header:
                            this.ReadHeaderChunk(pngMetadata, chunk.Data.Array);
                            break;

                        case PngChunkType.Physical:
                            this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan());
                            break;

                        case PngChunkType.Gamma:
                            this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan());
                            break;

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

                            this.ReadScanlines(chunk, image.Frames.RootFrame, pngMetadata);

                            break;

                        case PngChunkType.Palette:
                            var pal = new byte[chunk.Length];
                            Buffer.BlockCopy(chunk.Data.Array, 0, pal, 0, chunk.Length);
                            this.palette = pal;
                            break;

                        case PngChunkType.Transparency:
                            var alpha = new byte[chunk.Length];
                            Buffer.BlockCopy(chunk.Data.Array, 0, alpha, 0, chunk.Length);
                            this.paletteAlpha = alpha;
                            this.AssignTransparentMarkers(alpha, pngMetadata);
                            break;

                        case PngChunkType.Text:
                            this.ReadTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.CompressedText:
                            this.ReadCompressedTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.InternationalText:
                            this.ReadInternationalTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.Exif:
                            if (!this.ignoreMetadata)
                            {
                                var exifData = new byte[chunk.Length];
                                Buffer.BlockCopy(chunk.Data.Array, 0, exifData, 0, chunk.Length);
                                metadata.ExifProfile = new ExifProfile(exifData);
                            }

                            break;

                        case PngChunkType.End:
                            this.isEndChunkReached = true;
                            break;
                        }
                    }
                    finally
                    {
                        chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
                    }
                }

                if (image is null)
                {
                    PngThrowHelper.ThrowNoData();
                }

                return(image);
            }
            finally
            {
                this.scanline?.Dispose();
                this.previousScanline?.Dispose();
            }
        }
Пример #4
0
        /// <inheritdoc/>
        public IImageInfo Identify(BufferedReadStream stream)
        {
            var         metadata    = new ImageMetadata();
            PngMetadata pngMetadata = metadata.GetPngMetadata();

            this.currentStream = stream;
            this.currentStream.Skip(8);
            try
            {
                while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
                {
                    try
                    {
                        switch (chunk.Type)
                        {
                        case PngChunkType.Header:
                            this.ReadHeaderChunk(pngMetadata, chunk.Data.Array);
                            break;

                        case PngChunkType.Physical:
                            this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan());
                            break;

                        case PngChunkType.Gamma:
                            this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan());
                            break;

                        case PngChunkType.Data:
                            this.SkipChunkDataAndCrc(chunk);
                            break;

                        case PngChunkType.Text:
                            this.ReadTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.CompressedText:
                            this.ReadCompressedTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.InternationalText:
                            this.ReadInternationalTextChunk(pngMetadata, chunk.Data.Array.AsSpan(0, chunk.Length));
                            break;

                        case PngChunkType.Exif:
                            if (!this.ignoreMetadata)
                            {
                                var exifData = new byte[chunk.Length];
                                Buffer.BlockCopy(chunk.Data.Array, 0, exifData, 0, chunk.Length);
                                metadata.ExifProfile = new ExifProfile(exifData);
                            }

                            break;

                        case PngChunkType.End:
                            this.isEndChunkReached = true;
                            break;
                        }
                    }
                    finally
                    {
                        chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
                    }
                }
            }
            finally
            {
                this.scanline?.Dispose();
                this.previousScanline?.Dispose();
            }

            if (this.header.Width == 0 && this.header.Height == 0)
            {
                PngThrowHelper.ThrowNoHeader();
            }

            return(new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata));
        }