Table of Contents

Class RasterInfo

Namespace
Egami.Formats
Assembly
Egami.dll

What a file's header says, read without decoding pixels.

public sealed record RasterInfo : IEquatable<RasterInfo>
Inheritance
RasterInfo
Implements
Inherited Members

Examples

/// <summary>A minimal format: "RAW8", width and height as big-endian numbers, then RGBA rows.</summary>
public static class Raw8Format
{
    public static FormatInfo Info { get; } = new()
    {
        Name = "RAW8",
        Extensions = ["raw8"],
        SignatureLength = 4,
        Matches = header => header.StartsWith("RAW8"u8),
        Reader = new Reader(),
        Writer = new Writer(),
    };

    private sealed class Reader : IFormatReader
    {
        public RasterInfo ReadInfo(EgamiInput input, ReaderOptions options)
        {
            (int width, int height) = Header(input);
            return new RasterInfo { Format = Info, Width = width, Height = height, Layout = Rgba8.Layout, FrameCount = 1, EstimatedBytes = 4L * width * height };
        }

        public Raster<TPixel> Read<TPixel>(EgamiInput input, ReaderOptions options)
            where TPixel : unmanaged, IPixelType<TPixel>
        {
            (int width, int height) = Header(input);

            // CreateRaster checks the size against the safety limits before allocating.
            Raster<TPixel> raster = input.CreateRaster<TPixel>(width, height);
            using IMemoryOwner<byte> row = input.RentScratch(width * 4);
            for (int y = 0; y < height; y++)
            {
                input.ReadExactly(row.Memory.Span[..(width * 4)]);
                PixelConvert.Convert<Rgba8, TPixel>(MemoryMarshal.Cast<byte, Rgba8>(row.Memory.Span[..(width * 4)]), raster.Row(y));
            }

            return raster;
        }

        public Raster Read(EgamiInput input, ReaderOptions options) => Read<Rgba8>(input, options);

        private static (int Width, int Height) Header(EgamiInput input)
        {
            input.Skip(4);
            return ((int)input.ReadUInt32BigEndian(), (int)input.ReadUInt32BigEndian());
        }
    }

    private sealed class Writer : IFormatWriter
    {
        public void Write<TPixel>(Raster<TPixel> raster, Stream output, WriterOptions options)
            where TPixel : unmanaged, IPixelType<TPixel>
        {
            Span<byte> header = stackalloc byte[12];
            "RAW8"u8.CopyTo(header);
            BinaryPrimitives.WriteUInt32BigEndian(header[4..], (uint)raster.Width);
            BinaryPrimitives.WriteUInt32BigEndian(header[8..], (uint)raster.Height);
            output.Write(header);
            Rgba8[] row = new Rgba8[raster.Width];
            for (int y = 0; y < raster.Height; y++)
            {
                PixelConvert.Convert<TPixel, Rgba8>(raster.Row(y), row);
                output.Write(MemoryMarshal.AsBytes(row.AsSpan()));
            }
        }
    }
}

Properties

Access

Gets whether a RasterDecoder streams this image's rows or decodes it into a buffer first. Set by Probe(Stream, EgamiContext?, ReaderOptions?) and the decoder; formats need not set it.

public RasterAccess Access { get; init; }

Property Value

RasterAccess

EstimatedBytes

Gets an estimate of the bytes a full load in the natural pixel type would allocate, so large images can be rejected before decoding.

public long EstimatedBytes { get; init; }

Property Value

long

Format

Gets the format.

public required FormatInfo Format { get; init; }

Property Value

FormatInfo

FrameCount

Gets the number of frames, or null if finding out would need more than the header.

public int? FrameCount { get; init; }

Property Value

int?

HasMetadata

Gets whether the header shows any metadata, such as EXIF, ICC, XMP or text.

public bool HasMetadata { get; init; }

Property Value

bool

Height

Gets the height in pixels.

public required int Height { get; init; }

Property Value

int

ImageCount

Gets how many images LoadAll(Stream, EgamiContext?, ReaderOptions?) would return: 1 for formats that hold one image (an animation is one image), the page count of a TIFF, or null when finding out would need more than the header.

public int? ImageCount { get; init; }

Property Value

int?

Layout

Gets the layout of the pixel type Load(Stream, EgamiContext?, ReaderOptions?) would return.

public required PixelLayoutInfo Layout { get; init; }

Property Value

PixelLayoutInfo

LoopCount

Gets how many times an animation plays (0 for forever), as LoopCount would say, or null for formats without animation.

public int? LoopCount { get; init; }

Property Value

int?

Orientation

Gets the EXIF orientation: how the stored pixels must be turned to show the image upright. Load returns the pixels as stored; apply this with AutoOrient. Normal when the file says nothing.

public ImageOrientation Orientation { get; init; }

Property Value

ImageOrientation

Width

Gets the width in pixels.

public required int Width { get; init; }

Property Value

int

WorkingBytes

Gets the most bytes a RasterDecoder holds while decoding with the same options, besides the caller's band or target. Set by Probe(Stream, EgamiContext?, ReaderOptions?) and the decoder; formats need not set it.

public long WorkingBytes { get; init; }

Property Value

long