private int ReadChunkLength(PngChunk chunk) { byte[] lengthBuffer = new byte[4]; int numBytes = _stream.Read(lengthBuffer, 0, 4); //if (numBytes.IsBetween(1, 3)) if (numBytes >= 1 && numBytes <= 3) { throw new ImageFormatException("Image stream is not valid!"); } Array.Reverse(lengthBuffer); chunk.Length = BitConverter.ToInt32(lengthBuffer, 0); return(numBytes); }
private byte[] ReadChunkType(PngChunk chunk) { byte[] typeBuffer = new byte[4]; int numBytes = _stream.Read(typeBuffer, 0, 4); if (numBytes.IsBetween(1, 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); }
private void ReadChunkData(PngChunk chunk) { chunk.Data = new byte[chunk.Length]; _stream.Read(chunk.Data, 0, chunk.Length); }
/// <summary> /// Decodes the image from the specified stream and sets /// the data to image. /// </summary> /// <param name="image">The image, where the data should be set to. /// Cannot be null (Nothing in Visual Basic).</param> /// <param name="stream">The stream, where the image should be /// decoded from. Cannot be null (Nothing in Visual Basic).</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="image"/> is null (Nothing in Visual Basic).</para> /// <para>- or -</para> /// <para><paramref name="stream"/> is null (Nothing in Visual Basic).</para> /// </exception> public void Decode(ExtendedImage image, Stream stream) { _image = image; _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.Physical) { ReadPhysicalChunk(currentChunk.Data); } 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.Text) { ReadTextChunk(currentChunk.Data); } else if (currentChunk.Type == PngChunkTypes.End) { isEndChunckReached = true; } } 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); } image.SetPixels(_header.Width, _header.Height, pixels); } }
private int ReadChunkLength(PngChunk chunk) { byte[] lengthBuffer = new byte[4]; int numBytes = _stream.Read(lengthBuffer, 0, 4); if (numBytes.IsBetween(1, 3)) { throw new ImageFormatException("Image stream is not valid!"); } Array.Reverse(lengthBuffer); chunk.Length = BitConverter.ToInt32(lengthBuffer, 0); return numBytes; }
private byte[] ReadChunkType(PngChunk chunk) { byte[] typeBuffer = new byte[4]; int numBytes = _stream.Read(typeBuffer, 0, 4); if (numBytes.IsBetween(1, 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; }
private void ReadChunkCrc(PngChunk chunk, byte[] typeBuffer) { byte[] crcBuffer = new byte[4]; int numBytes = _stream.Read(crcBuffer, 0, 4); if (numBytes.IsBetween(1, 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!"); } }
private PngChunk ReadChunk() { PngChunk chunk = new PngChunk(); if (ReadChunkLength(chunk) == 0) { return null; } byte[] typeBuffer = ReadChunkType(chunk); ReadChunkData(chunk); ReadChunkCrc(chunk, typeBuffer); return chunk; }
private void ReadChunkCrc(PngChunk chunk, byte[] typeBuffer) { byte[] crcBuffer = new byte[4]; int numBytes = _stream.Read(crcBuffer, 0, 4); //if (numBytes.IsBetween(1, 3)) 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); CRC32Calculator crc32Cal = new CRC32Calculator(); crc32Cal.SlurpBlock(typeBuffer); crc32Cal.SlurpBlock(chunk.Data); //if (crc.Value != chunk.Crc) if ((uint)crc32Cal.Crc32Result != chunk.Crc) { throw new ImageFormatException("CRC Error. PNG Image chunk is corrupt!"); } }