Example #1
0
            private byte[] ReadChunkType(PngChunk chunk)
            {
                byte[] typeBuffer = new byte[4];

                int numBytes = _stream.Read(typeBuffer, 0, 4);

                if (numBytes >= 1 && numBytes <= 3)
                {
                    throw new ImageFormatException("Image stream is not valid!");
                }

                char[] chars = new char[4];
                chars[0] = (char)typeBuffer[0];
                chars[1] = (char)typeBuffer[1];
                chars[2] = (char)typeBuffer[2];
                chars[3] = (char)typeBuffer[3];

                chunk.Type = new string(chars);

                return(typeBuffer);
            }
Example #2
0
            public Image Decode(Stream stream)
            {
                _stream = stream;
                _stream.Seek(8, SeekOrigin.Current);

                bool isEndChunckReached = false;

                PngChunk currentChunk = null;

                byte[] palette      = null;
                byte[] paletteAlpha = null;

                using (MemoryStream dataStream = new MemoryStream())
                {
                    while ((currentChunk = ReadChunk()) != null)
                    {
                        if (isEndChunckReached)
                        {
                            throw new ImageFormatException("Image does not end with end chunk.");
                        }

                        if (currentChunk.Type == PngChunkTypes.Header)
                        {
                            ReadHeaderChunk(currentChunk.Data);

                            ValidateHeader();
                        }
                        else if (currentChunk.Type == PngChunkTypes.Data)
                        {
                            dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length);
                        }
                        else if (currentChunk.Type == PngChunkTypes.Palette)
                        {
                            palette = currentChunk.Data;
                        }
                        else if (currentChunk.Type == PngChunkTypes.PaletteAlpha)
                        {
                            paletteAlpha = currentChunk.Data;
                        }
                        else if (currentChunk.Type == PngChunkTypes.End)
                        {
                            isEndChunckReached = true;
                        }
                    }

                    if (_header.Width > Image.MaxWidth || _header.Height > Image.MaxHeight)
                    {
                        throw new ArgumentOutOfRangeException(
                                  $"The input png '{ _header.Width }x{ _header.Height }' is bigger then the max allowed size '{ Image.MaxWidth }x{ Image.MaxHeight }'");
                    }

                    byte[] pixels = new byte[_header.Width * _header.Height * 4];

                    PngColorTypeInformation colorTypeInformation = _colorTypes[_header.ColorType];

                    if (colorTypeInformation != null)
                    {
                        IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);

                        ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation);
                    }

                    return(new Image(_header.Width, _header.Height, pixels));
                }
            }
Example #3
0
            private int ReadChunkLength(PngChunk chunk)
            {
                byte[] lengthBuffer = new byte[4];

                int numBytes = _stream.Read(lengthBuffer, 0, 4);
                if (numBytes >= 1 && numBytes <= 3)
                {
                    throw new ImageFormatException("Image stream is not valid!");
                }

                Array.Reverse(lengthBuffer);

                chunk.Length = BitConverter.ToInt32(lengthBuffer, 0);

                return numBytes;
            }
Example #4
0
            private byte[] ReadChunkType(PngChunk chunk)
            {
                byte[] typeBuffer = new byte[4];

                int numBytes = _stream.Read(typeBuffer, 0, 4);
                if (numBytes >= 1 && numBytes <= 3)
                {
                    throw new ImageFormatException("Image stream is not valid!");
                }

                char[] chars = new char[4];
                chars[0] = (char)typeBuffer[0];
                chars[1] = (char)typeBuffer[1];
                chars[2] = (char)typeBuffer[2];
                chars[3] = (char)typeBuffer[3];

                chunk.Type = new string(chars);

                return typeBuffer;
            }
Example #5
0
            private void ReadChunkData(PngChunk chunk)
            {
                if (chunk.Length > MaxChunkSize)
                {
                    throw new ArgumentOutOfRangeException($"Png chunk size '{ chunk.Length }' excceeds the '{ MaxChunkSize }'");
                }

                chunk.Data = new byte[chunk.Length];

                _stream.Read(chunk.Data, 0, chunk.Length);
            }
Example #6
0
            private void ReadChunkCrc(PngChunk chunk, byte[] typeBuffer)
            {
                byte[] crcBuffer = new byte[4];

                int numBytes = _stream.Read(crcBuffer, 0, 4);
                if (numBytes >= 1 && numBytes <= 3)
                {
                    throw new ImageFormatException("Image stream is not valid!");
                }

                Array.Reverse(crcBuffer);

                chunk.Crc = BitConverter.ToUInt32(crcBuffer, 0);

                Crc32 crc = new Crc32();
                crc.Update(typeBuffer);
                crc.Update(chunk.Data);

                if (crc.Value != chunk.Crc)
                {
                    throw new ImageFormatException("CRC Error. PNG Image chunk is corrupt!");
                }
            }
Example #7
0
            private PngChunk ReadChunk()
            {
                PngChunk chunk = new PngChunk();

                if (ReadChunkLength(chunk) == 0)
                {
                    return null;
                }

                byte[] typeBuffer = ReadChunkType(chunk);

                ReadChunkData(chunk);
                ReadChunkCrc(chunk, typeBuffer);

                return chunk;
            }