Phaeyz.Png 0.0.0

dotnet add package Phaeyz.Png --version 0.0.0
                    
NuGet\Install-Package Phaeyz.Png -Version 0.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Phaeyz.Png" Version="0.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Phaeyz.Png" Version="0.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Phaeyz.Png" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Phaeyz.Png --version 0.0.0
                    
#r "nuget: Phaeyz.Png, 0.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Phaeyz.Png@0.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Phaeyz.Png&version=0.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Phaeyz.Png&version=0.0.0
                    
Install as a Cake Tool

Phaeyz

Phaeyz is a set of libraries created and polished over time for use with other projects, and made available here for convenience.

All Phaeyz libraries may be found here.

Phaeyz.Png

API documentation for Phaeyz.Png library is here.

This library contains classes which allow for deserializing PNG (Portable Network Graphics), editing and adding PNG chunks, as well as serializing it back out. Additionally there is utility for validating and correcting chunk order, and deserializing and serializing compressed strings within chunks. The deserializer and serializer was written such that if chunk types are not built-in or supported by Phaeyz.Png, they are stored as generic chunks, and chunk types can be extended to make them strongly typed.

Note this library does not protect you from creating non-standard PNG. Some chunks may be required and in certain orders in some contexts. Furthermore, this library only provides raw structural data for PNG, and currently does not provide decoding and encoding of image data -- though image data will be readily available through this library.

For more information on PNG, see PNG on Wikipedia and/or PNG Specification on W3.

Here are some highlights of this library.

PngMetadata (deserializing)

using FileStream fileStream = File.OpenRead(filePath);
using MarshalStream inputStream = new MarshalStream(fileStream, false); // Used to efficiently read file
// Some files have back-to-back PNG streams, where the second is a thumbnail or grayscale version.
// Instead of using ReadFromStreamAsync, ReadAllFromStreamAsync may extract them all into a list.
List<PngMetadata> pngMetadatas = await PngMetadata.ReadAllFromStreamAsync(inputStream);
foreach (PngMetadata pngMetadata in pngMetadatas)
{
    Exif? exif = pngMetadata.FindFirst<Exif>(); // Get the Exif segment
}

PngMetadata (serializing)

using FileStream fileStream = File.OpenRead(filePath);
using MarshalStream inputStream = new MarshalStream(fileStream, false); // Used to efficiently read file
// Some files have back-to-back PNG streams, where the second is a thumbnail or grayscale version.
// Instead of using ReadFromStreamAsync, ReadAllFromStreamAsync may extract them all into a list.
List<PngMetadata> pngMetadatas = await PngMetadata.ReadAllFromStreamAsync(inputStream);
// Make an output stream
using MemoryStream memoryStream = new();
using MarshalStream outputStream = new MarshalStream(memoryStream, false); // Used to efficient write file
await PngMetadata.WriteAllToStreamAsync(outputStream, pngMetadatas); // Can write all PNG metadata
// Can also write independent PNG metadata
foreach (PngMetadata pngMetadata in pngMetadatas)
{
    await pngMetadata.WriteToStreamAsync(outputStream);
}

PngMetadata (removing chunks)

using FileStream fileStream = File.OpenRead(filePath);
using MarshalStream inputStream = new MarshalStream(fileStream, false); // Used to efficiently read file
// Some files have back-to-back PNG streams, where the second is a thumbnail or grayscale version.
// Instead of using ReadFromStreamAsync, ReadAllFromStreamAsync may extract them all into a list.
List<PngMetadata> pngMetadatas = await PngMetadata.ReadAllFromStreamAsync(inputStream);
foreach (PngMetadata pngMetadata in pngMetadatas)
{
    // PngMetadata is basically a collection of chunks, and chunks may be removed
    pngMetadata.RemoveAll<TextualData>(); // Remove all chunks of this type
    pngMetadata.RemoveAll<CompressedTextualData>(); // Remove all chunks of this type
    pngMetadata.RemoveAll(ChunkType.InternationalTextualData); // May also use ChunkType enum.
}

PngMetadata (automatically fix chunk order)

PngMetadata pngMetadata = new();
// Add chunks
pngMetadata.Chunks.Add(new ImageEnd());
pngMetadata.Chunks.Add(new ImageHeader());
pngMetadata.Chunks.Add(new ImageData());
// Fix the order - will change to head, data, then end.
// Prefer to always do this before serializing to ensure PNG chunk order is to spec.
pngMetadata.ValidateAndReorderChunks();

ChunkDefinitions (custom segments)

// Define custom chunk.
[Chunk("tESt")] // Define the chunk type. May also specify AllowMultiple = true.
[OrderBeforeChunks("IDAT")] // These hints are used during automatic reordering.
public class CustomChunk : Chunk
{
    public byte[] Data { get; set; } = [];
    public override async ValueTask ReadFromStreamAsync(MarshalStream stream, int chunkLength, CancellationToken cancellationToken)
    {
        Data = new byte[chunkLength];
        await stream.ReadExactlyAsync(Data, cancellationToken).ConfigureAwait(false);
    }
    public override int ValidateAndComputeLength() => Data.Length;
    public override async ValueTask WriteToStreamAsync(MarshalStream stream, CancellationToken cancellationToken)
    {
        await stream.WriteAsync(Data, cancellationToken).ConfigureAwait(false);
    }
}

// Define the chunk
ChunkDefinitions chunkDefinitions = new(ChunkDefinitions.Default);
chunkDefinitions.Add<CustomChunk>();
// Now deserialize a stream with support for that chunk.
using FileStream fileStream = File.OpenRead(filePath);
using MarshalStream inputStream = new MarshalStream(fileStream, false); // Used to efficiently read file
// Some files have back-to-back PNG streams, where the second is a thumbnail or grayscale version.
// Instead of using ReadFromStreamAsync, ReadAllFromStreamAsync may extract them all into a list.
// Notice chunkDefinitions is passed in here.
List<PngMetadata> pngMetadatas = await PngMetadata.ReadAllFromStreamAsync(inputStream, chunkDefinitions);
foreach (PngMetadata pngMetadata in pngMetadatas)
{
    CustomChunk? customChunk = pngMetadata.FindFirst<CustomChunk>(); // Now fetch the custom chunk
}

Licensing

This project is licensed under GNU General Public License v3.0, which means you can use it for personal or educational purposes for free. However, donations are always encouraged to support the ongoing development of adding new features and resolving issues.

If you plan to use this code for commercial purposes or within an organization, we kindly ask for a donation to support the project's development. Any reasonably sized donation amount which reflects the perceived value of using Phaeyz in your product or service is accepted.

Donation Options

There are several ways to support Phaeyz with a donation. Perhaps the best way is to use Patreon so that recurring small donations continue to support the development of Phaeyz.

Your support is greatly appreciated and helps me continue to improve and maintain Phaeyz!

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.0 204 3/8/2025