PNG and APNG
Egami reads and writes PNG and its animated form, APNG: every color type and bit depth, interlaced files, transparency, text, EXIF, XMP and ICC profiles.
Reading
A PNG loads in its own layout: Gray8, Gray16, GrayAlpha8, Rgb8, Rgba8 or Rgba16. An APNG loads as Rgba8, or
Rgba16 for 16-bit files, with every frame composited to full size through every disposal and blend, as a browser shows it.
Damage is handled as the Diagnostics page lists under Png.: ancillary chunks with a bad checksum are
ignored, and when the image data ends early the rows not decoded are transparent black.
Writing
using FileStream output = File.Create("duck-small.png");
image.Save(output, PngFormat.Info, new PngWriterOptions
{
Reduce = true, // the smallest exact form: no alpha if all opaque, gray or a palette when nothing is lost
CompressionLevel = 9, // 0 (fastest) to 9 (smallest); 5 by default
});
| Option | Default | Does |
|---|---|---|
ColorType, BitDepth |
The pixel type's own | Force a layout, such as PngColorType.Palette |
Reduce |
false |
Scan the image and write the smallest exact form |
Palette |
256 colors, Floyd–Steinberg | How a palette is built when ColorType is Palette and the image has more colors |
CompressionLevel |
5 | zlib level, 0 to 9 |
Filter |
Adaptive |
Row filter, or one fixed filter |
FirstFrameOnly |
false |
Write a still PNG from an animation |
Interlace |
false |
Write Adam7, so a viewer can show a coarse image early; files are usually larger |
ParallelCompression |
false |
Compress images with more than 4 MiB of image data on several cores |
Interlace is never taken from the source: an interlaced PNG is written plain unless you set it. With ParallelCompression,
the image data is cut into fixed bands of 1 MiB that compress on up to EgamiContext.MaxParallelism threads. The file is the
same on any machine and at any thread count, and in Egami's tests it was 0.1% to 0.3% larger; a 24-megapixel photo saved
8 times as fast on 12 cores. Smaller images are written exactly as with the option off.
image.Save("duck-large.png", new PngWriterOptions
{
ParallelCompression = true, // big images compress on several cores; the same file at any thread count
Interlace = true, // Adam7: a coarse image shows before the whole file has arrived
});
Kept for round trips in PngDetails: gamma, chromaticities, sRGB intent, cICP, the ICC profile name, and every chunk Egami does
not read itself.
The writer also takes a palette you force, a fixed filter and a zlib strategy, and writes chunks you add to PngDetails:
// Force a palette, choose a filter and a zlib strategy, and keep a private chunk.
((PngDetails)image.Metadata.FormatDetails!).OtherChunks.Add(
new PngChunk("prVt", "hello"u8.ToArray(), PngChunkPosition.AfterImageData));
image.Save("duck-palette.png", new PngWriterOptions
{
ColorType = PngColorType.Palette,
Filter = PngFilterMode.Paeth,
CompressionStrategy = PngCompressionStrategy.Filtered,
});
APNG
Saving a raster with more than one frame as PNG writes an APNG. APNG keeps full color and partial alpha, so nothing is
quantized. Each frame stores only the rectangle that changed, and blends with Over when that stores less. Set
PngWriterOptions.FirstFrameOnly to write a still PNG from an animation. The animation guide covers
frames, delays and loops.