Enum SaveKeeps
What a writer keeps of a raster, as it is about to write it, for ReportLosses(string, SaveKeeps): everything the raster has that is not named here is reported as lost.
[Flags]
public enum SaveKeeps
Fields
Alpha = 1Alpha, or binary transparency.
Cmyk = 8CMYK inks.
Comment = 1024Text entries keyed "Comment" only.
Exif = 32The EXIF block.
FloatingPoint = 4Floating-point samples, values outside 0 to 1 included.
Frames = 16Every frame or page.
GainMap = 4096An HDR gain map (HDR Design question 11), or the caller's choice to leave it out.
Icc = 256The ICC profile.
Iptc = 128The IPTC datasets.
Metadata = Exif | Xmp | Iptc | Icc | Text | ResolutionEvery kind of metadata.
None = 0Nothing beyond 8-bit RGB or gray pixels.
Resolution = 2048The resolution.
Text = 512Every text entry.
Wide = 2Samples deeper than 8 bits.
Xmp = 64The XMP packet.
Examples
/// <summary>The same RAW8 format, streaming: rows go in and out one at a time, so RasterDecoder, RasterEncoder and Transcode stream it.</summary>
public static class StreamingRaw8Format
{
public static FormatInfo Info { get; } = Raw8Format.Info with { Reader = new Reader(), Writer = new Writer() };
private sealed class Reader : IFormatReader, IRowFormatReader
{
private static readonly IFormatReader Whole = Raw8Format.Info.Reader!;
public RasterInfo ReadInfo(EgamiInput input, ReaderOptions options) => Whole.ReadInfo(input, options) with { Access = RasterAccess.Streamed };
public Raster<TPixel> Read<TPixel>(EgamiInput input, ReaderOptions options)
where TPixel : unmanaged, IPixelType<TPixel> => Whole.Read<TPixel>(input, options);
public Raster Read(EgamiInput input, ReaderOptions options) => Whole.Read(input, options);
// The open image reads each row when it is asked for; the decoder crops, reduces and converts after it.
public RowReader Open(EgamiInput input, ReaderOptions options)
{
input.Skip(4);
int width = (int)input.ReadUInt32BigEndian();
int height = (int)input.ReadUInt32BigEndian();
// No raster checks the size here, so check it before the row buffer is allocated.
input.CheckFrameSize(width, height);
return new Rows(input, width, height);
}
}
private sealed class Rows(EgamiInput input, int width, int height) : RowReader<Rgba8>
{
private readonly Rgba8[] _row = new Rgba8[width];
private int _next;
private bool _started;
public override int Width => width;
public override int Height => height;
public override Metadata.RasterMetadata Metadata { get; } = new();
public override Metadata.FrameMetadata? NextFrame()
{
if (_started)
{
return null;
}
_started = true;
return new Metadata.FrameMetadata();
}
public override void ReadRow<TPixel>(int y, int x, Span<TPixel> destination)
{
for (; _next <= y; _next++)
{
input.ReadExactly(MemoryMarshal.AsBytes(_row.AsSpan()));
}
PixelConvert.Convert<Rgba8, TPixel>(_row.AsSpan(x, destination.Length), destination);
}
}
private sealed class Writer : IFormatWriter, IRowFormatWriter
{
public void Write<TPixel>(Raster<TPixel> raster, Stream output, WriterOptions options)
where TPixel : unmanaged, IPixelType<TPixel> => Raw8Format.Info.Writer!.Write(raster, output, options);
// Save, SaveAsync, RasterEncoder and Transcode all write through the encoder.
public RowEncoder<TPixel> Start<TPixel>(Stream output, EncodeStart<TPixel> start)
where TPixel : unmanaged, IPixelType<TPixel>
{
// RAW8 keeps 8-bit RGBA and nothing else: deeper samples or metadata are reported as lost.
start.ReportLosses("RAW8", SaveKeeps.Alpha);
return new Encoder<TPixel>(output, start.Width, start.Height);
}
}
private sealed class Encoder<TPixel> : RowEncoder<TPixel>
where TPixel : unmanaged, IPixelType<TPixel>
{
private readonly Stream _output;
private readonly Rgba8[] _row;
public Encoder(Stream output, int width, int height)
{
_output = output;
_row = new Rgba8[width];
Span<byte> header = stackalloc byte[12];
"RAW8"u8.CopyTo(header);
BinaryPrimitives.WriteUInt32BigEndian(header[4..], (uint)width);
BinaryPrimitives.WriteUInt32BigEndian(header[8..], (uint)height);
output.Write(header);
}
public override void WriteRow(ReadOnlySpan<TPixel> row)
{
PixelConvert.Convert<TPixel, Rgba8>(row, _row);
_output.Write(MemoryMarshal.AsBytes(_row.AsSpan()));
}
public override void Complete()
{
}
}
}