/// <summary> /// Read the PNG image from the bytes. /// </summary> /// <param name="bytes">The bytes of the PNG data to be read.</param> /// <param name="settings">Settings to apply when opening the PNG.</param> /// <returns>The <see cref="Png"/> data from the bytes.</returns> public static Png Open(byte[] bytes, PngOpenerSettings settings) { using (var memoryStream = new MemoryStream(bytes)) { return(PngOpener.Open(memoryStream, settings)); } }
/// <summary> /// Read the PNG from the file path. /// </summary> /// <param name="filePath">The path to the PNG file to open.</param> /// <param name="settings">Settings to apply when opening the PNG.</param> /// <remarks>This will open the file to obtain a <see cref="FileStream"/> so will lock the file during reading.</remarks> /// <returns>The <see cref="Png"/> data from the file.</returns> public static Png Open(string filePath, PngOpenerSettings settings) { using (var fileStream = File.OpenRead(filePath)) { return(Open(fileStream, settings)); } }
public static Png Open(Stream stream, PngOpenerSettings settings) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanRead) { throw new ArgumentException($"The provided stream of type {stream.GetType().FullName} was not readable."); } var validHeader = HasValidHeader(stream); if (!validHeader.IsValid) { throw new ArgumentException($"The provided stream did not start with the PNG header. Got {validHeader}."); } var crc = new byte[4]; var imageHeader = ReadImageHeader(stream, crc); var hasEncounteredImageEnd = false; Palette palette = null; using (var output = new MemoryStream()) { using (var memoryStream = new MemoryStream()) { while (TryReadChunkHeader(stream, out var header)) { if (hasEncounteredImageEnd) { if (settings?.DisallowTrailingData == true) { throw new InvalidOperationException($"Found another chunk {header} after already reading the IEND chunk."); } break; } var bytes = new byte[header.Length]; var read = stream.Read(bytes, 0, bytes.Length); if (read != bytes.Length) { throw new InvalidOperationException($"Did not read {header.Length} bytes for the {header} header, only found: {read}."); } if (header.IsCritical) { switch (header.Name) { case "PLTE": if (header.Length % 3 != 0) { throw new InvalidOperationException($"Palette data must be multiple of 3, got {header.Length}."); } // Ignore palette data unless the header.ColorType indicates that the image is paletted. if (imageHeader.ColorType.HasFlag(ColorType.PaletteUsed)) { palette = new Palette(bytes); } break; case "IDAT": memoryStream.Write(bytes, 0, bytes.Length); break; case "IEND": hasEncounteredImageEnd = true; break; default: throw new NotSupportedException($"Encountered critical header {header} which was not recognised."); } } read = stream.Read(crc, 0, crc.Length); if (read != 4) { throw new InvalidOperationException($"Did not read 4 bytes for the CRC, only found: {read}."); } var result = (int)Crc32.Calculate(Encoding.ASCII.GetBytes(header.Name), bytes); var crcActual = (crc[0] << 24) + (crc[1] << 16) + (crc[2] << 8) + crc[3]; if (result != crcActual) { throw new InvalidOperationException($"CRC calculated {result} did not match file {crcActual} for chunk: {header.Name}."); } settings?.ChunkVisitor?.Visit(stream, imageHeader, header, bytes, crc); } memoryStream.Flush(); memoryStream.Seek(2, SeekOrigin.Begin); using (var deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress)) { deflateStream.CopyTo(output); deflateStream.Close(); } } var bytesOut = output.ToArray(); var(bytesPerPixel, samplesPerPixel) = Decoder.GetBytesAndSamplesPerPixel(imageHeader); bytesOut = Decoder.Decode(bytesOut, imageHeader, bytesPerPixel, samplesPerPixel); return(new Png(imageHeader, new RawPngData(bytesOut, bytesPerPixel, palette, imageHeader))); } }
/// <summary> /// Read the PNG image from the stream. /// </summary> /// <param name="stream">The stream containing PNG data to be read.</param> /// <param name="settings">Settings to apply when opening the PNG.</param> /// <returns>The <see cref="Png"/> data from the stream.</returns> public static Png Open(Stream stream, PngOpenerSettings settings) => PngOpener.Open(stream, settings);