/// <summary> /// Calculates the length of the given chunk. /// </summary> /// <param name="chunk">The chunk.</param> /// <exception cref="ImageFormatException"> /// Thrown if the input stream is not valid. /// </exception> private void ReadChunkLength(PngChunk chunk) { int numBytes = this.currentStream.Read(this.chunkLengthBuffer, 0, 4); if (numBytes >= 1 && numBytes <= 3) { throw new ImageFormatException("Image stream is not valid!"); } if (numBytes <= 0) { chunk.Length = -1; return; } this.chunkLengthBuffer.ReverseBytes(); chunk.Length = BitConverter.ToInt32(this.chunkLengthBuffer, 0); }
/// <summary> /// Reads a chunk from the stream. /// </summary> /// <returns> /// The <see cref="PngChunk"/>. /// </returns> private PngChunk ReadChunk() { PngChunk chunk = new PngChunk(); if (this.ReadChunkLength(chunk) == 0) { return(null); } if (chunk.Length <= 0) { return(null); } this.ReadChunkType(chunk); this.ReadChunkData(chunk); this.ReadChunkCrc(chunk); return(chunk); }
/// <summary> /// Reads a chunk from the stream. /// </summary> /// <returns> /// The <see cref="PngChunk"/>. /// </returns> private PngChunk ReadChunk() { var chunk = new PngChunk(); this.ReadChunkLength(chunk); if (chunk.Length < 0) { return null; } this.ReadChunkType(chunk); if (chunk.Type == PngChunkTypes.Data) { return chunk; } this.ReadChunkData(chunk); this.ReadChunkCrc(chunk); return chunk; }
/// <summary> /// Identifies the chunk type from the chunk. /// </summary> /// <param name="chunk">The chunk.</param> /// <returns> /// The <see cref="T:byte[]"/> containing identifying information. /// </returns> /// <exception cref="ImageFormatException"> /// Thrown if the input stream is not valid. /// </exception> private byte[] ReadChunkType(PngChunk chunk) { byte[] typeBuffer = new byte[4]; int numBytes = this.currentStream.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); }
/// <summary> /// Reads the cycle redundancy chunk from the data. /// </summary> /// <param name="chunk">The chunk.</param> /// <exception cref="ImageFormatException"> /// Thrown if the input stream is not valid or corrupt. /// </exception> private void ReadChunkCrc(PngChunk chunk) { int numBytes = this.currentStream.Read(this.crcBuffer, 0, 4); if (numBytes >= 1 && numBytes <= 3) { throw new ImageFormatException("Image stream is not valid!"); } this.crcBuffer.ReverseBytes(); chunk.Crc = BitConverter.ToUInt32(this.crcBuffer, 0); this.crc.Reset(); this.crc.Update(this.chunkTypeBuffer); this.crc.Update(chunk.Data, 0, chunk.Length); if (this.crc.Value != chunk.Crc) { throw new ImageFormatException("CRC Error. PNG Image chunk is corrupt!"); } }
/// <summary> /// Reads the chunk data from the stream. /// </summary> /// <param name="chunk">The chunk.</param> private void ReadChunkData(PngChunk chunk) { chunk.Data = new byte[chunk.Length]; this.currentStream.Read(chunk.Data, 0, chunk.Length); }
/// <summary> /// Reads the chunk data from the stream. /// </summary> /// <param name="chunk">The chunk.</param> private void ReadChunkData(PngChunk chunk) { // We rent the buffer here to return it afterwards in Decode() chunk.Data = ArrayPool<byte>.Shared.Rent(chunk.Length); this.currentStream.Read(chunk.Data, 0, chunk.Length); }